use crate::windows_native::error::{WinError, WinResult};
use crate::BusType;
use std::mem::{size_of, zeroed};
use std::ptr::null;
use windows_sys::core::GUID;
use windows_sys::Win32::Devices::Properties::{DEVPROPTYPE, DEVPROP_TYPE_GUID};
use windows_sys::Win32::Foundation::{
CloseHandle, DEVPROPKEY, FALSE, HANDLE, INVALID_HANDLE_VALUE, PROPERTYKEY, TRUE,
};
use windows_sys::Win32::System::Threading::{CreateEventW, INFINITE};
use windows_sys::Win32::System::IO::{GetOverlappedResultEx, OVERLAPPED};
#[allow(clippy::missing_safety_doc)]
pub unsafe trait DeviceProperty {
const TYPE: DEVPROPTYPE;
fn create_sized(bytes: usize) -> Self;
fn as_ptr_mut(&mut self) -> *mut u8;
fn validate(&self) {}
}
unsafe impl DeviceProperty for GUID {
const TYPE: DEVPROPTYPE = DEVPROP_TYPE_GUID;
fn create_sized(bytes: usize) -> Self {
assert_eq!(bytes, size_of::<GUID>());
GUID::from_u128(0)
}
fn as_ptr_mut(&mut self) -> *mut u8 {
(self as *mut GUID) as *mut u8
}
}
pub trait PropertyKey: Copy {
fn as_ptr(&self) -> *const DEVPROPKEY;
}
impl PropertyKey for DEVPROPKEY {
fn as_ptr(&self) -> *const DEVPROPKEY {
self
}
}
impl PropertyKey for PROPERTYKEY {
fn as_ptr(&self) -> *const DEVPROPKEY {
self as *const PROPERTYKEY as _
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum InternalBusType {
Unknown,
Usb,
Bluetooth,
BluetoothLE,
I2c,
Spi,
}
impl From<InternalBusType> for BusType {
fn from(value: InternalBusType) -> Self {
match value {
InternalBusType::Unknown => BusType::Unknown,
InternalBusType::Usb => BusType::Usb,
InternalBusType::Bluetooth => BusType::Bluetooth,
InternalBusType::BluetoothLE => BusType::Bluetooth,
InternalBusType::I2c => BusType::I2c,
InternalBusType::Spi => BusType::Spi,
}
}
}
pub struct Handle(HANDLE);
impl Handle {
pub fn from_raw(handle: HANDLE) -> Self {
Self(handle)
}
pub fn as_raw(&self) -> HANDLE {
self.0
}
}
impl Drop for Handle {
fn drop(&mut self) {
if self.0 != INVALID_HANDLE_VALUE {
unsafe {
CloseHandle(self.0);
}
}
self.0 = INVALID_HANDLE_VALUE;
}
}
pub struct Overlapped(OVERLAPPED);
impl Overlapped {
pub fn event_handle(&self) -> HANDLE {
self.0.hEvent
}
pub fn as_raw(&mut self) -> *mut OVERLAPPED {
&mut self.0
}
pub fn get_result(&mut self, handle: &Handle, timeout: Option<u32>) -> WinResult<usize> {
let mut bytes_written = 0;
let cr = unsafe {
GetOverlappedResultEx(
handle.as_raw(),
self.as_raw(),
&mut bytes_written,
timeout.unwrap_or(INFINITE),
FALSE,
)
};
ensure!(cr == TRUE, Err(WinError::last()));
Ok(bytes_written as usize)
}
}
unsafe impl Send for Overlapped {}
impl Default for Overlapped {
fn default() -> Self {
Overlapped(unsafe {
OVERLAPPED {
hEvent: CreateEventW(null(), FALSE, FALSE, null()),
..zeroed()
}
})
}
}
impl Drop for Overlapped {
fn drop(&mut self) {
if self.0.hEvent != INVALID_HANDLE_VALUE {
unsafe {
CloseHandle(self.0.hEvent);
}
}
self.0.hEvent = INVALID_HANDLE_VALUE;
}
}