commit
221867978b
24 changed files with 108 additions and 129 deletions
|
|
@ -37,6 +37,6 @@ fn inspect_device(dev: DeviceInfo) {
|
|||
for config in dev.configurations() {
|
||||
println!("{config:#?}");
|
||||
}
|
||||
println!("");
|
||||
println!("");
|
||||
println!();
|
||||
println!();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,5 +61,5 @@ fn inspect_device(dev: DeviceInfo) {
|
|||
println!(" Serial({i_serial}): {s:?}");
|
||||
}
|
||||
|
||||
println!("");
|
||||
println!();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
use std::{
|
||||
collections::BTreeMap,
|
||||
fmt::{Debug, Display},
|
||||
io::ErrorKind,
|
||||
iter,
|
||||
num::NonZeroU8,
|
||||
ops::Deref,
|
||||
|
|
@ -192,7 +191,7 @@ impl DeviceDescriptor {
|
|||
/// This ignores any trailing data after the `bLength` specified in the descriptor.
|
||||
pub fn new(buf: &[u8]) -> Option<Self> {
|
||||
let Some(buf) = buf.get(0..DESCRIPTOR_LEN_DEVICE as usize) else {
|
||||
if buf.len() != 0 {
|
||||
if !buf.is_empty() {
|
||||
warn!(
|
||||
"device descriptor buffer is {} bytes, need {}",
|
||||
buf.len(),
|
||||
|
|
@ -222,6 +221,7 @@ impl DeviceDescriptor {
|
|||
}
|
||||
|
||||
#[allow(unused)]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn from_fields(
|
||||
usb_version: u16,
|
||||
class: u8,
|
||||
|
|
@ -360,7 +360,7 @@ impl<'a> ConfigurationDescriptor<'a> {
|
|||
/// This ignores any trailing data after the length specified in `wTotalLen`.
|
||||
pub fn new(buf: &[u8]) -> Option<ConfigurationDescriptor> {
|
||||
if buf.len() < DESCRIPTOR_LEN_CONFIGURATION as usize {
|
||||
if buf.len() != 0 {
|
||||
if !buf.is_empty() {
|
||||
warn!(
|
||||
"config descriptor buffer is {} bytes, need {}",
|
||||
buf.len(),
|
||||
|
|
@ -734,7 +734,7 @@ impl std::error::Error for ActiveConfigurationError {}
|
|||
|
||||
impl From<ActiveConfigurationError> for Error {
|
||||
fn from(value: ActiveConfigurationError) -> Self {
|
||||
Error::new(ErrorKind::Other, value)
|
||||
Error::other(value)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ impl Device {
|
|||
|
||||
self.configurations()
|
||||
.find(|c| c.configuration_value() == active)
|
||||
.ok_or_else(|| ActiveConfigurationError {
|
||||
.ok_or(ActiveConfigurationError {
|
||||
configuration_value: active,
|
||||
})
|
||||
}
|
||||
|
|
@ -661,7 +661,7 @@ impl<EpType: BulkOrInterrupt, Dir: EndpointDirection> Endpoint<EpType, Dir> {
|
|||
///
|
||||
/// ## Panics
|
||||
/// * if there are no transfers pending (that is, if [`Self::pending()`]
|
||||
/// would return 0).
|
||||
/// would return 0).
|
||||
pub fn poll_next_complete(&mut self, cx: &mut Context<'_>) -> Poll<Completion> {
|
||||
self.backend.poll_next_complete(cx)
|
||||
}
|
||||
|
|
@ -676,7 +676,7 @@ impl<EpType: BulkOrInterrupt, Dir: EndpointDirection> Endpoint<EpType, Dir> {
|
|||
///
|
||||
/// ## Panics
|
||||
/// * if there are no transfers pending (that is, if [`Self::pending()`]
|
||||
/// would return 0).
|
||||
/// would return 0).
|
||||
pub fn wait_next_complete(&mut self, timeout: Duration) -> Option<Completion> {
|
||||
self.backend.wait_next_complete(timeout)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -457,7 +457,7 @@ impl UsbControllerType {
|
|||
match lower_s
|
||||
.find("hci")
|
||||
.filter(|i| *i > 0)
|
||||
.and_then(|i| lower_s.bytes().nth(i - 1))
|
||||
.and_then(|i| lower_s.as_bytes().get(i - 1))
|
||||
{
|
||||
Some(b'x') => Some(UsbControllerType::XHCI),
|
||||
Some(b'e') => Some(UsbControllerType::EHCI),
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ impl Stream for HotplugWatch {
|
|||
|
||||
/// Event returned from the [`HotplugWatch`] stream.
|
||||
#[derive(Debug)]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
pub enum HotplugEvent {
|
||||
/// A device has been connected.
|
||||
Connected(DeviceInfo),
|
||||
|
|
|
|||
|
|
@ -472,7 +472,7 @@ impl LinuxDevice {
|
|||
|
||||
let mut dst = [0u8; 1];
|
||||
let r = usbfs::control(
|
||||
&fd,
|
||||
fd,
|
||||
usbfs::CtrlTransfer {
|
||||
bRequestType: request_type(Direction::In, ControlType::Standard, Recipient::Device),
|
||||
bRequest: REQUEST_GET_CONFIGURATION,
|
||||
|
|
@ -525,7 +525,7 @@ impl LinuxDevice {
|
|||
"No available configurations for device fd {}",
|
||||
fd.as_raw_fd()
|
||||
);
|
||||
return Err(ErrorKind::Other.into());
|
||||
Err(ErrorKind::Other.into())
|
||||
}
|
||||
|
||||
pub(crate) fn speed(&self) -> Option<Speed> {
|
||||
|
|
@ -595,8 +595,7 @@ impl LinuxInterface {
|
|||
let mut state = self.state.lock().unwrap();
|
||||
if !state.endpoints.is_empty() {
|
||||
// TODO: Use ErrorKind::ResourceBusy once compatible with MSRV
|
||||
return Err(Error::new(
|
||||
ErrorKind::Other,
|
||||
return Err(Error::other(
|
||||
"must drop endpoints before changing alt setting",
|
||||
));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,8 +82,7 @@ impl SysfsPath {
|
|||
SysfsError(
|
||||
p,
|
||||
SysfsErrorKind::Parse(format!(
|
||||
"Failed to read filename for readlink attribute {}",
|
||||
attr
|
||||
"Failed to read filename for readlink attribute {attr}",
|
||||
)),
|
||||
)
|
||||
})
|
||||
|
|
@ -94,7 +93,7 @@ impl SysfsPath {
|
|||
fs::read_dir(&self.0)
|
||||
.ok()
|
||||
.into_iter()
|
||||
.flat_map(|x| x)
|
||||
.flatten()
|
||||
.filter_map(|f| f.ok())
|
||||
.filter(|f| f.file_type().ok().is_some_and(|t| t.is_dir()))
|
||||
.map(|f| SysfsPath(f.path()))
|
||||
|
|
@ -117,7 +116,7 @@ impl FromHexStr for u16 {
|
|||
}
|
||||
}
|
||||
|
||||
const SYSFS_USB_PREFIX: &'static str = "/sys/bus/usb/devices/";
|
||||
const SYSFS_USB_PREFIX: &str = "/sys/bus/usb/devices/";
|
||||
|
||||
pub fn list_devices() -> impl MaybeFuture<Output = Result<impl Iterator<Item = DeviceInfo>, Error>>
|
||||
{
|
||||
|
|
@ -215,9 +214,9 @@ pub fn probe_device(path: SysfsPath) -> Result<DeviceInfo, SysfsError> {
|
|||
device_version: path.read_attr_hex("bcdDevice")?,
|
||||
usb_version: path.parse_attr("version", |s| {
|
||||
// in sysfs, `bcdUSB`` is formatted as `%2x.%02x, so we have to parse it back.
|
||||
s.split('.')
|
||||
.map(|x| u16::from_hex_str(x))
|
||||
.fold(Ok::<u16, ParseIntError>(0), |a, b| Ok((a? << 8) | b?))
|
||||
s.split('.').try_fold(0, |a, b| {
|
||||
Ok::<u16, ParseIntError>((a << 8) | u16::from_hex_str(b)?)
|
||||
})
|
||||
})?,
|
||||
class: path.read_attr_hex("bDeviceClass")?,
|
||||
subclass: path.read_attr_hex("bDeviceSubClass")?,
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ impl TransferData {
|
|||
let mut t = TransferData::new(0x00, TransferType::Control);
|
||||
let mut buffer = Buffer::new(SETUP_PACKET_SIZE.checked_add(data.data.len()).unwrap());
|
||||
buffer.extend_from_slice(&data.setup_packet());
|
||||
buffer.extend_from_slice(&data.data);
|
||||
buffer.extend_from_slice(data.data);
|
||||
t.set_buffer(buffer);
|
||||
t
|
||||
}
|
||||
|
|
@ -103,19 +103,19 @@ impl TransferData {
|
|||
|
||||
pub fn take_completion(&mut self) -> Completion {
|
||||
let status = self.status();
|
||||
let requested_len = (&mut *self).urb().buffer_length as u32;
|
||||
let requested_len = self.urb().buffer_length as u32;
|
||||
let actual_len = self.urb().actual_length as usize;
|
||||
let len = match Direction::from_address((&mut *self).urb().endpoint) {
|
||||
Direction::Out => (&mut *self).urb().buffer_length as u32,
|
||||
Direction::In => (&mut *self).urb().actual_length as u32,
|
||||
let len = match Direction::from_address(self.urb().endpoint) {
|
||||
Direction::Out => self.urb().buffer_length as u32,
|
||||
Direction::In => self.urb().actual_length as u32,
|
||||
};
|
||||
|
||||
let mut empty = ManuallyDrop::new(Vec::new());
|
||||
let ptr = mem::replace(&mut (&mut *self).urb_mut().buffer, empty.as_mut_ptr());
|
||||
let capacity = mem::replace(&mut (&mut *self).capacity, 0);
|
||||
(&mut *self).urb_mut().buffer_length = 0;
|
||||
(&mut *self).urb_mut().actual_length = 0;
|
||||
let allocator = mem::replace(&mut (&mut *self).allocator, Allocator::Default);
|
||||
let ptr = mem::replace(&mut self.urb_mut().buffer, empty.as_mut_ptr());
|
||||
let capacity = mem::replace(&mut self.capacity, 0);
|
||||
self.urb_mut().buffer_length = 0;
|
||||
self.urb_mut().actual_length = 0;
|
||||
let allocator = mem::replace(&mut self.allocator, Allocator::Default);
|
||||
|
||||
Completion {
|
||||
status,
|
||||
|
|
|
|||
|
|
@ -82,12 +82,8 @@ impl MacDevice {
|
|||
}
|
||||
};
|
||||
|
||||
let device_descriptor = device_descriptor_from_fields(&service).ok_or_else(|| {
|
||||
Error::new(
|
||||
ErrorKind::Other,
|
||||
"could not read properties for device descriptor",
|
||||
)
|
||||
})?;
|
||||
let device_descriptor = device_descriptor_from_fields(&service)
|
||||
.ok_or_else(|| Error::other("could not read properties for device descriptor"))?;
|
||||
|
||||
let active_config = if let Some(active_config) = guess_active_config(&device) {
|
||||
log::debug!("Active config from single descriptor is {}", active_config);
|
||||
|
|
@ -132,15 +128,14 @@ impl MacDevice {
|
|||
}
|
||||
|
||||
fn require_open_exclusive(&self) -> Result<(), Error> {
|
||||
let mut state = self.is_open_exclusive.lock().unwrap();
|
||||
if *state == false {
|
||||
let mut is_open_exclusive = self.is_open_exclusive.lock().unwrap();
|
||||
if !*is_open_exclusive {
|
||||
unsafe { check_iokit_return(call_iokit_function!(self.device.raw, USBDeviceOpen()))? };
|
||||
*state = true;
|
||||
*is_open_exclusive = true;
|
||||
}
|
||||
|
||||
if self.claimed_interfaces.load(Ordering::Relaxed) != 0 {
|
||||
return Err(Error::new(
|
||||
ErrorKind::Other,
|
||||
return Err(Error::other(
|
||||
"cannot perform this operation while interfaces are claimed",
|
||||
));
|
||||
}
|
||||
|
|
@ -187,14 +182,8 @@ impl MacDevice {
|
|||
.device
|
||||
.create_interface_iterator()?
|
||||
.find(|io_service| {
|
||||
let current_number = get_integer_property(io_service, "bInterfaceNumber");
|
||||
let found = current_number == Some(interface_number as i64);
|
||||
debug!(
|
||||
"Looking for interface to claim [n={interface_number}], examining interface [n={}]{}",
|
||||
current_number.map(|n| n.to_string()).unwrap_or_else(|| "unknown".to_string()),
|
||||
found.then(|| " (found)").unwrap_or("")
|
||||
);
|
||||
found
|
||||
get_integer_property(io_service, "bInterfaceNumber")
|
||||
== Some(interface_number as i64)
|
||||
})
|
||||
.ok_or(Error::new(ErrorKind::NotFound, "interface not found"))?;
|
||||
|
||||
|
|
@ -351,8 +340,7 @@ impl MacInterface {
|
|||
if !state.endpoints_used.is_empty() {
|
||||
// TODO: Use ErrorKind::ResourceBusy once compatible with MSRV
|
||||
|
||||
return Err(Error::new(
|
||||
ErrorKind::Other,
|
||||
return Err(Error::other(
|
||||
"must drop endpoints before changing alt setting",
|
||||
));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ fn usb_service_iter() -> Result<IoServiceIterator, Error> {
|
|||
unsafe {
|
||||
let dictionary = IOServiceMatching(kIOUSBDeviceClassName);
|
||||
if dictionary.is_null() {
|
||||
return Err(Error::new(ErrorKind::Other, "IOServiceMatching failed"));
|
||||
return Err(Error::other("IOServiceMatching failed"));
|
||||
}
|
||||
|
||||
let mut iterator = 0;
|
||||
|
|
@ -67,7 +67,7 @@ fn usb_controller_service_iter(
|
|||
UsbControllerType::VHCI => IOServiceMatching(kAppleUSBVHCI),
|
||||
};
|
||||
if dictionary.is_null() {
|
||||
return Err(Error::new(ErrorKind::Other, "IOServiceMatching failed"));
|
||||
return Err(Error::other("IOServiceMatching failed"));
|
||||
}
|
||||
|
||||
let mut iterator = 0;
|
||||
|
|
@ -271,7 +271,7 @@ fn parse_location_id(id: u32) -> Vec<u8> {
|
|||
while shift != 0 {
|
||||
let port = shift >> 28;
|
||||
chain.push(port as u8);
|
||||
shift = shift << 4;
|
||||
shift <<= 4;
|
||||
}
|
||||
|
||||
chain
|
||||
|
|
@ -281,18 +281,18 @@ fn parse_location_id(id: u32) -> Vec<u8> {
|
|||
/// we have all the fields to rebuild it exactly.
|
||||
pub(crate) fn device_descriptor_from_fields(device: &IoService) -> Option<DeviceDescriptor> {
|
||||
Some(DeviceDescriptor::from_fields(
|
||||
get_integer_property(&device, "bcdUSB")? as u16,
|
||||
get_integer_property(&device, "bDeviceClass")? as u8,
|
||||
get_integer_property(&device, "bDeviceSubClass")? as u8,
|
||||
get_integer_property(&device, "bDeviceProtocol")? as u8,
|
||||
get_integer_property(&device, "bMaxPacketSize0")? as u8,
|
||||
get_integer_property(&device, "idVendor")? as u16,
|
||||
get_integer_property(&device, "idProduct")? as u16,
|
||||
get_integer_property(&device, "bcdDevice")? as u16,
|
||||
get_integer_property(&device, "iManufacturer")? as u8,
|
||||
get_integer_property(&device, "iProduct")? as u8,
|
||||
get_integer_property(&device, "iSerialNumber")? as u8,
|
||||
get_integer_property(&device, "bNumConfigurations")? as u8,
|
||||
get_integer_property(device, "bcdUSB")? as u16,
|
||||
get_integer_property(device, "bDeviceClass")? as u8,
|
||||
get_integer_property(device, "bDeviceSubClass")? as u8,
|
||||
get_integer_property(device, "bDeviceProtocol")? as u8,
|
||||
get_integer_property(device, "bMaxPacketSize0")? as u8,
|
||||
get_integer_property(device, "idVendor")? as u16,
|
||||
get_integer_property(device, "idProduct")? as u16,
|
||||
get_integer_property(device, "bcdDevice")? as u16,
|
||||
get_integer_property(device, "iManufacturer")? as u8,
|
||||
get_integer_property(device, "iProduct")? as u8,
|
||||
get_integer_property(device, "iSerialNumber")? as u8,
|
||||
get_integer_property(device, "bNumConfigurations")? as u8,
|
||||
))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use std::{
|
||||
ffi::{c_char, c_void},
|
||||
io::ErrorKind,
|
||||
mem::ManuallyDrop,
|
||||
sync::Mutex,
|
||||
task::{Context, Poll, Waker},
|
||||
|
|
@ -80,7 +79,7 @@ impl MacHotplugWatch {
|
|||
let dictionary = unsafe {
|
||||
let d = IOServiceMatching(kIOUSBDeviceClassName);
|
||||
if d.is_null() {
|
||||
return Err(Error::new(ErrorKind::Other, "IOServiceMatching failed"));
|
||||
return Err(Error::other("IOServiceMatching failed"));
|
||||
}
|
||||
CFDictionary::wrap_under_create_rule(d)
|
||||
};
|
||||
|
|
@ -163,10 +162,7 @@ fn register_notification(
|
|||
);
|
||||
|
||||
if r != kIOReturnSuccess {
|
||||
return Err(Error::new(
|
||||
ErrorKind::Other,
|
||||
"Failed to register notification",
|
||||
));
|
||||
return Err(Error::other("Failed to register notification"));
|
||||
}
|
||||
let mut iter = IoServiceIterator::new(iter);
|
||||
|
||||
|
|
@ -181,6 +177,8 @@ unsafe extern "C" fn callback(refcon: *mut c_void, _iterator: io_iterator_t) {
|
|||
debug!("hotplug event callback");
|
||||
let id = refcon as usize;
|
||||
if let Some(waker) = WAKERS.lock().unwrap().get_mut(id) {
|
||||
waker.take().map(|w| w.wake());
|
||||
if let Some(w) = waker.take() {
|
||||
w.wake()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,10 +122,9 @@ pub(crate) fn check_iokit_return(r: IOReturn) -> Result<(), Error> {
|
|||
#[deny(unreachable_patterns)]
|
||||
match r {
|
||||
io_kit_sys::ret::kIOReturnSuccess => Ok(()),
|
||||
io_kit_sys::ret::kIOReturnExclusiveAccess => Err(Error::new(
|
||||
ErrorKind::Other,
|
||||
"could not be opened for exclusive access",
|
||||
)),
|
||||
io_kit_sys::ret::kIOReturnExclusiveAccess => {
|
||||
Err(Error::other("could not be opened for exclusive access"))
|
||||
}
|
||||
io_kit_sys::ret::kIOReturnNotFound => Err(Error::new(ErrorKind::NotFound, "not found")),
|
||||
_ => Err(Error::from_raw_os_error(r)),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,10 +80,7 @@ impl IoKitDevice {
|
|||
|
||||
if raw_device_plugin.is_null() {
|
||||
error!("IOKit indicated it successfully created a PlugInInterface, but the pointer was NULL");
|
||||
return Err(Error::new(
|
||||
ErrorKind::Other,
|
||||
"Could not create PlugInInterface",
|
||||
));
|
||||
return Err(Error::other("Could not create PlugInInterface"));
|
||||
}
|
||||
|
||||
let device_plugin = PluginInterface::new(raw_device_plugin);
|
||||
|
|
@ -109,10 +106,10 @@ impl IoKitDevice {
|
|||
return Ok(IoKitDevice { raw: raw_device });
|
||||
}
|
||||
|
||||
return Err(Error::new(
|
||||
Err(Error::new(
|
||||
ErrorKind::NotFound,
|
||||
"Couldn't create device after retries",
|
||||
));
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -216,10 +213,7 @@ impl IoKitInterface {
|
|||
|
||||
if raw_interface_plugin.is_null() {
|
||||
error!("IOKit indicated it successfully created a PlugInInterface, but the pointer was NULL");
|
||||
return Err(Error::new(
|
||||
ErrorKind::Other,
|
||||
"Could not create PlugInInterface",
|
||||
));
|
||||
return Err(Error::other("Could not create PlugInInterface"));
|
||||
}
|
||||
|
||||
let interface_plugin = PluginInterface::new(raw_interface_plugin);
|
||||
|
|
@ -240,7 +234,7 @@ impl IoKitInterface {
|
|||
panic!("query_interface returned a null pointer, which Apple says is impossible");
|
||||
}
|
||||
|
||||
return Ok(IoKitInterface { raw });
|
||||
Ok(IoKitInterface { raw })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@ use windows_sys::Win32::{
|
|||
Devices::Usb::{
|
||||
self, WinUsb_ControlTransfer, WinUsb_Free, WinUsb_GetAssociatedInterface,
|
||||
WinUsb_Initialize, WinUsb_ReadPipe, WinUsb_ResetPipe, WinUsb_SetCurrentAlternateSetting,
|
||||
WinUsb_SetPipePolicy, WinUsb_WritePipe, WINUSB_INTERFACE_HANDLE, WINUSB_SETUP_PACKET,
|
||||
WinUsb_SetPipePolicy, WinUsb_WritePipe, USB_DEVICE_DESCRIPTOR, WINUSB_INTERFACE_HANDLE,
|
||||
WINUSB_SETUP_PACKET,
|
||||
},
|
||||
Foundation::{GetLastError, ERROR_IO_PENDING, ERROR_NOT_FOUND, FALSE, HANDLE, TRUE},
|
||||
System::IO::{CancelIoEx, OVERLAPPED},
|
||||
|
|
@ -78,7 +79,9 @@ impl WindowsDevice {
|
|||
|
||||
// Safety: Windows API struct is repr(C), packed, and we're assuming Windows is little-endian
|
||||
let device_descriptor = unsafe {
|
||||
&transmute::<_, [u8; DESCRIPTOR_LEN_DEVICE as usize]>(connection_info.device_desc)
|
||||
&transmute::<USB_DEVICE_DESCRIPTOR, [u8; DESCRIPTOR_LEN_DEVICE as usize]>(
|
||||
connection_info.device_desc,
|
||||
)
|
||||
};
|
||||
let device_descriptor = DeviceDescriptor::new(device_descriptor)
|
||||
.ok_or_else(|| Error::new(ErrorKind::InvalidData, "invalid device descriptor"))?;
|
||||
|
|
@ -100,7 +103,7 @@ impl WindowsDevice {
|
|||
config_descriptors,
|
||||
speed: connection_info.speed,
|
||||
active_config: connection_info.active_config,
|
||||
devinst: devinst,
|
||||
devinst,
|
||||
handles: Mutex::new(BTreeMap::new()),
|
||||
}))
|
||||
})
|
||||
|
|
@ -260,7 +263,7 @@ unsafe impl Sync for WinusbFileHandle {}
|
|||
|
||||
impl WinusbFileHandle {
|
||||
fn new(path: &WCStr, first_interface: u8) -> Result<Self, Error> {
|
||||
let handle = create_file(&path)?;
|
||||
let handle = create_file(path)?;
|
||||
super::events::register(&handle)?;
|
||||
|
||||
let winusb_handle = unsafe {
|
||||
|
|
@ -466,12 +469,11 @@ impl WindowsInterface {
|
|||
let mut state = self.state.lock().unwrap();
|
||||
if !state.endpoints.is_empty() {
|
||||
// TODO: Use ErrorKind::ResourceBusy once compatible with MSRV
|
||||
return Err(Error::new(
|
||||
ErrorKind::Other,
|
||||
return Err(Error::other(
|
||||
"must drop endpoints before changing alt setting",
|
||||
));
|
||||
}
|
||||
let r = WinUsb_SetCurrentAlternateSetting(self.winusb_handle, alt_setting.into());
|
||||
let r = WinUsb_SetCurrentAlternateSetting(self.winusb_handle, alt_setting);
|
||||
if r == TRUE {
|
||||
debug!(
|
||||
"Set interface {} alt setting to {alt_setting}",
|
||||
|
|
@ -550,7 +552,7 @@ impl WindowsInterface {
|
|||
self.winusb_handle,
|
||||
endpoint,
|
||||
buf,
|
||||
len.try_into().expect("transfer size should fit in u32"),
|
||||
len,
|
||||
null_mut(),
|
||||
ptr as *mut OVERLAPPED,
|
||||
),
|
||||
|
|
@ -558,7 +560,7 @@ impl WindowsInterface {
|
|||
self.winusb_handle,
|
||||
endpoint,
|
||||
buf,
|
||||
len.try_into().expect("transfer size should fit in u32"),
|
||||
len,
|
||||
null_mut(),
|
||||
ptr as *mut OVERLAPPED,
|
||||
),
|
||||
|
|
@ -611,7 +613,7 @@ impl WindowsInterface {
|
|||
// Safety: Transfer was not submitted, so we still own it
|
||||
// and must complete it in place of the event thread.
|
||||
unsafe {
|
||||
(&mut *t.as_ptr()).overlapped.Internal = err as _;
|
||||
(*t.as_ptr()).overlapped.Internal = err as _;
|
||||
notify_completion::<TransferData>(t.as_ptr());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ pub fn probe_device(devinst: DevInst) -> Option<DeviceInfo> {
|
|||
})
|
||||
.collect()
|
||||
} else {
|
||||
list_interfaces_from_desc(&hub_port, info.active_config).unwrap_or(Vec::new())
|
||||
list_interfaces_from_desc(&hub_port, info.active_config).unwrap_or_default()
|
||||
};
|
||||
|
||||
interfaces.sort_unstable_by_key(|i| i.interface_number);
|
||||
|
|
@ -241,10 +241,7 @@ pub(crate) fn get_winusb_device_path(dev: DevInst) -> Result<WCString, Error> {
|
|||
let paths = dev.interfaces(GUID_DEVINTERFACE_USB_DEVICE);
|
||||
|
||||
let Some(path) = paths.iter().next() else {
|
||||
return Err(Error::new(
|
||||
ErrorKind::Other,
|
||||
"Failed to find device path for WinUSB device",
|
||||
));
|
||||
return Err(Error::other("Failed to find device path for WinUSB device"));
|
||||
};
|
||||
|
||||
Ok(path.to_owned())
|
||||
|
|
@ -301,8 +298,7 @@ pub(crate) fn get_usbccgp_winusb_device_path(child: DevInst) -> Result<WCString,
|
|||
|
||||
let paths = child.interfaces(guid);
|
||||
let Some(path) = paths.iter().next() else {
|
||||
return Err(Error::new(
|
||||
ErrorKind::Other,
|
||||
return Err(Error::other(
|
||||
"Failed to find device path for WinUSB interface",
|
||||
));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ impl IoCompletionPort {
|
|||
fn register(&self, handle: &OwnedHandle) -> Result<(), Error> {
|
||||
unsafe {
|
||||
let r = CreateIoCompletionPort(raw_handle(handle), raw_handle(&self.0), 0, 0);
|
||||
if r == ptr::null_mut() {
|
||||
if r.is_null() {
|
||||
let err = std::io::Error::last_os_error();
|
||||
error!("CreateIoCompletionPort (register) failed: {err:?}");
|
||||
Err(err)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use std::{
|
||||
collections::VecDeque,
|
||||
ffi::c_void,
|
||||
io::ErrorKind,
|
||||
mem::size_of,
|
||||
ptr::{self, addr_of},
|
||||
sync::Mutex,
|
||||
|
|
@ -80,10 +79,7 @@ impl WindowsHotplugWatch {
|
|||
|
||||
if cr != CR_SUCCESS {
|
||||
error!("CM_Register_Notification failed: {cr}");
|
||||
return Err(Error::new(
|
||||
ErrorKind::Other,
|
||||
"Failed to initialize hotplug notifications",
|
||||
));
|
||||
return Err(Error::other("Failed to initialize hotplug notifications"));
|
||||
}
|
||||
|
||||
Ok(WindowsHotplugWatch {
|
||||
|
|
@ -165,6 +161,9 @@ unsafe extern "system" fn hotplug_callback(
|
|||
|
||||
debug!("Hotplug callback: action={action:?}, instance={device_instance}");
|
||||
inner.events.lock().unwrap().push_back((action, devinst));
|
||||
inner.waker.lock().unwrap().take().map(|w| w.wake());
|
||||
return ERROR_SUCCESS;
|
||||
if let Some(w) = inner.waker.lock().unwrap().take() {
|
||||
w.wake()
|
||||
}
|
||||
|
||||
ERROR_SUCCESS
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,8 +86,7 @@ impl HubHandle {
|
|||
if info.DeviceDescriptor.bDescriptorType != DESCRIPTOR_TYPE_DEVICE {
|
||||
// When the device is disconnected during this call, Windows is observed to
|
||||
// sometimes return an all-zero device descriptor.
|
||||
return Err(Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
return Err(Error::other(
|
||||
"IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX returned an invalid device descriptor",
|
||||
));
|
||||
}
|
||||
|
|
@ -187,10 +186,9 @@ impl HubHandle {
|
|||
let err = GetLastError();
|
||||
debug!("IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION failed: type={descriptor_type} index={descriptor_index} error={err:?}");
|
||||
Err(match err {
|
||||
ERROR_GEN_FAILURE => Error::new(
|
||||
ErrorKind::Other,
|
||||
"Descriptor request failed. Device might be suspended.",
|
||||
),
|
||||
ERROR_GEN_FAILURE => {
|
||||
Error::other("Descriptor request failed. Device might be suspended.")
|
||||
}
|
||||
_ => Error::from_raw_os_error(err as i32),
|
||||
})
|
||||
};
|
||||
|
|
@ -217,9 +215,9 @@ impl HubPort {
|
|||
pub fn by_child_devinst(devinst: DevInst) -> Result<HubPort, Error> {
|
||||
let parent_hub = devinst
|
||||
.parent()
|
||||
.ok_or_else(|| Error::new(ErrorKind::Other, "failed to find parent hub"))?;
|
||||
.ok_or_else(|| Error::other("failed to find parent hub"))?;
|
||||
let hub_handle = HubHandle::by_devinst(parent_hub)
|
||||
.ok_or_else(|| Error::new(ErrorKind::Other, "failed to open parent hub"))?;
|
||||
.ok_or_else(|| Error::other("failed to open parent hub"))?;
|
||||
let Some(port_number) = devinst.get_property::<u32>(DEVPKEY_Device_Address) else {
|
||||
return Err(Error::new(
|
||||
ErrorKind::NotConnected,
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ impl TransferData {
|
|||
let ptr = mem::replace(&mut self.buf, empty.as_mut_ptr());
|
||||
let capacity = mem::replace(&mut self.capacity, 0);
|
||||
let len = match Direction::from_address(self.endpoint) {
|
||||
Direction::Out => self.request_len as u32,
|
||||
Direction::Out => self.request_len,
|
||||
Direction::In => actual_len,
|
||||
};
|
||||
let requested_len = mem::replace(&mut self.request_len, 0);
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ impl From<&OsStr> for WCString {
|
|||
|
||||
impl Borrow<WCStr> for WCString {
|
||||
fn borrow(&self) -> &WCStr {
|
||||
&self
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -105,6 +105,12 @@ impl Buffer {
|
|||
self.len as usize
|
||||
}
|
||||
|
||||
/// Returns `true` if the buffer is empty.
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len == 0
|
||||
}
|
||||
|
||||
/// Requested length for IN transfer or actual length for OUT transfer.
|
||||
#[inline]
|
||||
pub fn requested_len(&self) -> usize {
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ impl<P> Pending<P> {
|
|||
fn state(&self) -> &AtomicU8 {
|
||||
// Get state without dereferencing as `TransferInner`, because
|
||||
// its `platform_data` may be mutably aliased.
|
||||
unsafe { &*(addr_of_mut!((*self.ptr.as_ptr()).state)) }
|
||||
unsafe { &*addr_of_mut!((*self.ptr.as_ptr()).state) }
|
||||
}
|
||||
|
||||
pub fn is_complete(&self) -> bool {
|
||||
|
|
@ -189,7 +189,7 @@ pub fn take_completed_from_queue<P>(queue: &mut VecDeque<Pending<P>>) -> Option<
|
|||
|
||||
pub fn take_completed_from_option<P>(option: &mut Option<Pending<P>>) -> Option<Idle<P>> {
|
||||
// TODO: use Option::take_if once supported by MSRV
|
||||
if option.as_mut().map_or(false, |next| next.is_complete()) {
|
||||
if option.as_mut().is_some_and(|next| next.is_complete()) {
|
||||
option.take().map(|t| unsafe { t.into_idle() })
|
||||
} else {
|
||||
None
|
||||
|
|
|
|||
|
|
@ -70,8 +70,8 @@ impl From<TransferError> for io::Error {
|
|||
TransferError::Cancelled => io::Error::new(io::ErrorKind::Interrupted, value),
|
||||
TransferError::Stall => io::Error::new(io::ErrorKind::ConnectionReset, value),
|
||||
TransferError::Disconnected => io::Error::new(io::ErrorKind::ConnectionAborted, value),
|
||||
TransferError::Fault => io::Error::new(io::ErrorKind::Other, value),
|
||||
TransferError::Unknown(_) => io::Error::new(io::ErrorKind::Other, value),
|
||||
TransferError::Fault => io::Error::other(value),
|
||||
TransferError::Unknown(_) => io::Error::other(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue