Merge pull request #45 from kevinmehall/winusb-control-interface
Document and warn on case where WinUSB changes the passed control transfer index field to the interface number
This commit is contained in:
commit
2379cb1b2c
3 changed files with 49 additions and 8 deletions
|
|
@ -346,8 +346,13 @@ impl Interface {
|
|||
///
|
||||
/// ### Platform-specific notes
|
||||
///
|
||||
/// * On Linux, this takes a device-wide lock, so if you have multiple threads, you
|
||||
/// are better off using the async methods.
|
||||
/// * On Linux, this takes a device-wide lock, so if you have multiple
|
||||
/// threads, you are better off using the async methods.
|
||||
/// * On Windows, if the `recipient` is `Interface`, the WinUSB driver sends
|
||||
/// the interface number in the least significant byte of `index`,
|
||||
/// overriding any value passed. A warning is logged if the passed `index`
|
||||
/// least significant byte differs from the interface number, and this may
|
||||
/// become an error in the future.
|
||||
pub fn control_in_blocking(
|
||||
&self,
|
||||
control: Control,
|
||||
|
|
@ -361,8 +366,13 @@ impl Interface {
|
|||
///
|
||||
/// ### Platform-specific notes
|
||||
///
|
||||
/// * On Linux, this takes a device-wide lock, so if you have multiple threads, you
|
||||
/// are better off using the async methods.
|
||||
/// * On Linux, this takes a device-wide lock, so if you have multiple
|
||||
/// threads, you are better off using the async methods.
|
||||
/// * On Windows, if the `recipient` is `Interface`, the WinUSB driver sends
|
||||
/// the interface number in the least significant byte of `index`,
|
||||
/// overriding any value passed. A warning is logged if the passed `index`
|
||||
/// least significant byte differs from the interface number, and this may
|
||||
/// become an error in the future.
|
||||
pub fn control_out_blocking(
|
||||
&self,
|
||||
control: Control,
|
||||
|
|
@ -394,6 +404,13 @@ impl Interface {
|
|||
/// })).into_result()?;
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
///
|
||||
/// ### Platform-specific notes
|
||||
/// * On Windows, if the `recipient` is `Interface`, the WinUSB driver sends
|
||||
/// the interface number in the least significant byte of `index`,
|
||||
/// overriding any value passed. A warning is logged if the passed `index`
|
||||
/// least significant byte differs from the interface number, and this may
|
||||
/// become an error in the future.
|
||||
pub fn control_in(&self, data: ControlIn) -> TransferFuture<ControlIn> {
|
||||
let mut t = self.backend.make_transfer(0, EndpointType::Control);
|
||||
t.submit::<ControlIn>(data);
|
||||
|
|
@ -422,6 +439,13 @@ impl Interface {
|
|||
/// })).into_result()?;
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
///
|
||||
/// ### Platform-specific notes
|
||||
/// * On Windows, if the `recipient` is `Interface`, the WinUSB driver sends
|
||||
/// the interface number in the least significant byte of `index`,
|
||||
/// overriding any value passed. A warning is logged if the passed `index`
|
||||
/// least significant byte differs from the interface number, and this may
|
||||
/// become an error in the future.
|
||||
pub fn control_out(&self, data: ControlOut) -> TransferFuture<ControlOut> {
|
||||
let mut t = self.backend.make_transfer(0, EndpointType::Control);
|
||||
t.submit::<ControlOut>(data);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use std::{
|
|||
time::Duration,
|
||||
};
|
||||
|
||||
use log::{debug, error, info};
|
||||
use log::{debug, error, info, warn};
|
||||
use windows_sys::Win32::{
|
||||
Devices::Usb::{
|
||||
WinUsb_ControlTransfer, WinUsb_Free, WinUsb_Initialize, WinUsb_SetCurrentAlternateSetting,
|
||||
|
|
@ -19,7 +19,7 @@ use windows_sys::Win32::{
|
|||
|
||||
use crate::{
|
||||
descriptors::{validate_config_descriptor, DESCRIPTOR_TYPE_CONFIGURATION},
|
||||
transfer::{Control, Direction, EndpointType, TransferError, TransferHandle},
|
||||
transfer::{Control, Direction, EndpointType, Recipient, TransferError, TransferHandle},
|
||||
DeviceInfo, Error,
|
||||
};
|
||||
|
||||
|
|
@ -125,6 +125,7 @@ impl WindowsDevice {
|
|||
|
||||
Ok(Arc::new(WindowsInterface {
|
||||
handle,
|
||||
interface,
|
||||
winusb_handle,
|
||||
}))
|
||||
}
|
||||
|
|
@ -139,6 +140,7 @@ impl WindowsDevice {
|
|||
|
||||
pub(crate) struct WindowsInterface {
|
||||
pub(crate) handle: OwnedHandle,
|
||||
pub(crate) interface: u8,
|
||||
pub(crate) winusb_handle: WINUSB_INTERFACE_HANDLE,
|
||||
}
|
||||
|
||||
|
|
@ -161,6 +163,11 @@ impl WindowsInterface {
|
|||
timeout: Duration,
|
||||
) -> Result<usize, TransferError> {
|
||||
info!("Blocking control {direction:?}, {len} bytes");
|
||||
|
||||
if control.recipient == Recipient::Interface && control.index as u8 != self.interface {
|
||||
warn!("WinUSB sends interface number instead of passed `index` when performing a control transfer with `Recipient::Interface`");
|
||||
}
|
||||
|
||||
let timeout_ms = timeout.as_millis().min(u32::MAX as u128) as u32;
|
||||
let r = WinUsb_SetPipePolicy(
|
||||
self.winusb_handle,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use std::{
|
|||
sync::Arc,
|
||||
};
|
||||
|
||||
use log::{debug, error};
|
||||
use log::{debug, error, warn};
|
||||
use windows_sys::Win32::{
|
||||
Devices::Usb::{
|
||||
WinUsb_ControlTransfer, WinUsb_GetOverlappedResult, WinUsb_ReadPipe, WinUsb_WritePipe,
|
||||
|
|
@ -22,7 +22,7 @@ use windows_sys::Win32::{
|
|||
|
||||
use crate::transfer::{
|
||||
notify_completion, Completion, ControlIn, ControlOut, EndpointType, PlatformSubmit,
|
||||
PlatformTransfer, RequestBuffer, ResponseBuffer, TransferError,
|
||||
PlatformTransfer, Recipient, RequestBuffer, ResponseBuffer, TransferError,
|
||||
};
|
||||
|
||||
use super::util::raw_handle;
|
||||
|
|
@ -228,6 +228,11 @@ impl PlatformSubmit<ControlIn> for TransferData {
|
|||
unsafe fn submit(&mut self, data: ControlIn, user_data: *mut c_void) {
|
||||
assert_eq!(self.endpoint, 0);
|
||||
assert_eq!(self.ep_type, EndpointType::Control);
|
||||
|
||||
if data.recipient == Recipient::Interface && data.index as u8 != self.interface.interface {
|
||||
warn!("WinUSB sends interface number instead of passed `index` when performing a control transfer with `Recipient::Interface`");
|
||||
}
|
||||
|
||||
addr_of_mut!((*self.event).ptr).write(user_data);
|
||||
|
||||
let mut buf = ManuallyDrop::new(Vec::with_capacity(data.length as usize));
|
||||
|
|
@ -270,6 +275,11 @@ impl PlatformSubmit<ControlOut<'_>> for TransferData {
|
|||
unsafe fn submit(&mut self, data: ControlOut, user_data: *mut c_void) {
|
||||
assert_eq!(self.endpoint, 0);
|
||||
assert_eq!(self.ep_type, EndpointType::Control);
|
||||
|
||||
if data.recipient == Recipient::Interface && data.index as u8 != self.interface.interface {
|
||||
warn!("WinUSB sends interface number instead of passed `index` when performing a control transfer with `Recipient::Interface`");
|
||||
}
|
||||
|
||||
addr_of_mut!((*self.event).ptr).write(user_data);
|
||||
|
||||
let mut buf = ManuallyDrop::new(data.data.to_vec());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue