use crate::windows_native::error::{check_boolean, WinError, WinResult};
use crate::windows_native::types::Handle;
use std::ffi::c_void;
use std::mem::{size_of, zeroed};
use windows_sys::core::GUID;
use windows_sys::Win32::Devices::HumanInterfaceDevice::{
HidD_FreePreparsedData, HidD_GetAttributes, HidD_GetHidGuid, HidD_GetPreparsedData,
HidP_GetCaps, HIDD_ATTRIBUTES, HIDP_CAPS, HIDP_STATUS_SUCCESS,
};
pub fn get_interface_guid() -> GUID {
unsafe {
let mut guid = zeroed();
HidD_GetHidGuid(&mut guid);
guid
}
}
pub fn get_hid_attributes(handle: &Handle) -> HIDD_ATTRIBUTES {
unsafe {
let mut attrib = HIDD_ATTRIBUTES {
Size: size_of::<HIDD_ATTRIBUTES>() as u32,
..zeroed()
};
HidD_GetAttributes(handle.as_raw(), &mut attrib);
attrib
}
}
#[repr(transparent)]
pub struct PreparsedData(isize);
impl Drop for PreparsedData {
fn drop(&mut self) {
unsafe {
HidD_FreePreparsedData(self.0);
}
}
}
impl PreparsedData {
pub fn load(handle: &Handle) -> WinResult<Self> {
let mut pp_data = 0;
check_boolean(unsafe { HidD_GetPreparsedData(handle.as_raw(), &mut pp_data) })?;
ensure!(pp_data != 0, Err(WinError::InvalidPreparsedData));
Ok(Self(pp_data))
}
#[allow(dead_code)]
pub fn as_ptr(&self) -> *const c_void {
self.0 as _
}
pub fn get_caps(&self) -> WinResult<HIDP_CAPS> {
unsafe {
let mut caps = zeroed();
let r = HidP_GetCaps(self.0, &mut caps);
ensure!(
r == HIDP_STATUS_SUCCESS,
Err(WinError::InvalidPreparsedData)
);
Ok(caps)
}
}
}