use crate::HidError;
use windows_sys::Win32::Devices::DeviceAndDriverInstallation::*;
use windows_sys::Win32::Foundation::*;
pub type WinResult<T> = Result<T, WinError>;
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum WinError {
Config(CONFIGRET),
Win32(Win32Error),
BufferTooSmall,
InvalidDeviceId,
InvalidDeviceNode,
NoSuchValue,
WrongPropertyDataType,
UnexpectedReturnSize,
InvalidPreparsedData,
WaitTimedOut,
}
impl WinError {
pub fn last() -> Self {
Self::from(Win32Error::last())
}
}
impl From<WinError> for HidError {
fn from(value: WinError) -> Self {
match value {
WinError::Win32(Win32Error::Generic(err)) => HidError::IoError {
error: std::io::Error::from_raw_os_error(err as _),
},
err => HidError::HidApiError {
message: format!("WinError: {:?}", err),
},
}
}
}
fn config_to_error(ret: CONFIGRET) -> WinError {
match ret {
CR_BUFFER_SMALL => WinError::BufferTooSmall,
CR_INVALID_DEVICE_ID => WinError::InvalidDeviceId,
CR_INVALID_DEVNODE => WinError::InvalidDeviceNode,
CR_NO_SUCH_VALUE => WinError::NoSuchValue,
ret => WinError::Config(ret),
}
}
pub fn check_config(ret: CONFIGRET, expected: CONFIGRET) -> WinResult<()> {
if ret == expected {
Ok(())
} else {
Err(config_to_error(ret))
}
}
pub fn check_boolean(ret: bool) -> WinResult<()> {
if !ret {
Err(Win32Error::last().into())
} else {
Ok(())
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Win32Error {
Generic(WIN32_ERROR),
Success,
IoPending,
WaitTimedOut,
}
impl Win32Error {
pub fn last() -> Self {
match unsafe { GetLastError() } {
NO_ERROR => Self::Success,
ERROR_IO_PENDING => Self::IoPending,
ERROR_IO_INCOMPLETE | WAIT_TIMEOUT => Self::WaitTimedOut,
code => Self::Generic(code),
}
}
}
impl From<Win32Error> for WinError {
fn from(value: Win32Error) -> Self {
match value {
Win32Error::WaitTimedOut => Self::WaitTimedOut,
err => Self::Win32(err),
}
}
}
impl From<Win32Error> for HidError {
fn from(value: Win32Error) -> Self {
HidError::from(WinError::from(value))
}
}