diff --git a/Cargo.toml b/Cargo.toml index 31dbd73..127d049 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,7 @@ windows-native = [ [dependencies] libc = "0.2" +cfg-if = "1" [target.'cfg(target_os = "linux")'.dependencies] udev = { version = "0.7", optional = true } diff --git a/src/lib.rs b/src/lib.rs index 8226763..1ef0831 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -58,36 +58,10 @@ //! [`HidDevice`] handles can access the same physical device. For backward compatibility this is //! an opt-in that can be enabled with the `macos-shared-device` feature flag. -extern crate libc; -#[cfg(all(feature = "linux-native", target_os = "linux"))] -extern crate nix; - -#[cfg(target_os = "windows")] -use windows_sys::core::GUID; - mod error; mod ffi; -#[cfg(hidapi)] -mod hidapi; - -#[cfg(all(feature = "linux-native", target_os = "linux"))] -#[cfg_attr(docsrs, doc(cfg(all(feature = "linux-native", target_os = "linux"))))] -mod linux_native; -#[cfg(target_os = "macos")] -#[cfg_attr(docsrs, doc(cfg(target_os = "macos")))] -mod macos; -#[cfg(target_os = "windows")] -#[cfg_attr(docsrs, doc(cfg(target_os = "windows")))] -mod windows; - -#[cfg(feature = "windows-native")] -#[cfg_attr( - docsrs, - doc(cfg(all(feature = "windows-native", target_os = "windows"))) -)] -mod windows_native; - +use cfg_if::cfg_if; use libc::wchar_t; use std::ffi::CStr; use std::ffi::CString; @@ -97,12 +71,54 @@ use std::sync::Mutex; pub use error::HidError; -#[cfg(hidapi)] -use crate::hidapi::HidApiBackend; -#[cfg(all(feature = "linux-native", target_os = "linux"))] -use linux_native::HidApiBackend; -#[cfg(all(feature = "windows-native", target_os = "windows"))] -use windows_native::HidApiBackend; +cfg_if! { + if #[cfg(all(feature = "linux-native", target_os = "linux"))] { + //#[cfg_attr(docsrs, doc(cfg(all(feature = "linux-native", target_os = "linux"))))] + mod linux_native; + use linux_native::HidApiBackend; + } else if #[cfg(all(feature = "windows-native", target_os = "windows"))] { + //#[cfg_attr(docsrs, doc(cfg(all(feature = "windows-native", target_os = "windows"))))] + mod windows_native; + use windows_native::HidApiBackend; + } else if #[cfg(hidapi)] { + mod hidapi; + use hidapi::HidApiBackend; + } else { + compile_error!("No backend selected"); + } +} + +// Automatically implement the top trait +cfg_if! { + if #[cfg(target_os = "windows")] { + #[cfg_attr(docsrs, doc(cfg(target_os = "windows")))] + mod windows; + use windows::GUID; + /// A trait with the extra methods that are available on Windows + trait HidDeviceBackendWindows { + /// Get the container ID for a HID device + fn get_container_id(&self) -> HidResult; + } + trait HidDeviceBackend: HidDeviceBackendBase + HidDeviceBackendWindows + Send {} + impl HidDeviceBackend for T where T: HidDeviceBackendBase + HidDeviceBackendWindows + Send {} + } else if #[cfg(target_os = "macos")] { + #[cfg_attr(docsrs, doc(cfg(target_os = "macos")))] + mod macos; + /// A trait with the extra methods that are available on macOS + trait HidDeviceBackendMacos { + /// Get the location ID for a [`HidDevice`] device. + fn get_location_id(&self) -> HidResult; + + /// Check if the device was opened in exclusive mode. + fn is_open_exclusive(&self) -> HidResult; + } + trait HidDeviceBackend: HidDeviceBackendBase + HidDeviceBackendMacos + Send {} + impl HidDeviceBackend for T where T: HidDeviceBackendBase + HidDeviceBackendMacos + Send {} + } else { + trait HidDeviceBackend: HidDeviceBackendBase + Send {} + impl HidDeviceBackend for T where T: HidDeviceBackendBase + Send {} + } +} pub type HidResult = Result; pub const MAX_REPORT_DESCRIPTOR_SIZE: usize = 4096; @@ -471,42 +487,6 @@ trait HidDeviceBackendBase { } } -/// A trait with the extra methods that are available on macOS -#[cfg(target_os = "macos")] -trait HidDeviceBackendMacos { - /// Get the location ID for a [`HidDevice`] device. - fn get_location_id(&self) -> HidResult; - - /// Check if the device was opened in exclusive mode. - fn is_open_exclusive(&self) -> HidResult; -} - -/// A trait with the extra methods that are available on macOS -#[cfg(target_os = "windows")] -trait HidDeviceBackendWindows { - /// Get the container ID for a HID device - fn get_container_id(&self) -> HidResult; -} - -#[cfg(not(any(target_os = "macos", target_os = "windows")))] -trait HidDeviceBackend: HidDeviceBackendBase + Send {} -#[cfg(target_os = "macos")] -trait HidDeviceBackend: HidDeviceBackendBase + HidDeviceBackendMacos + Send {} -#[cfg(target_os = "windows")] -trait HidDeviceBackend: HidDeviceBackendBase + HidDeviceBackendWindows + Send {} - -/// Automatically implement the top trait -#[cfg(not(any(target_os = "macos", target_os = "windows")))] -impl HidDeviceBackend for T where T: HidDeviceBackendBase + Send {} - -/// Automatically implement the top trait -#[cfg(target_os = "macos")] -impl HidDeviceBackend for T where T: HidDeviceBackendBase + HidDeviceBackendMacos + Send {} - -/// Automatically implement the top trait -#[cfg(target_os = "windows")] -impl HidDeviceBackend for T where T: HidDeviceBackendBase + HidDeviceBackendWindows + Send {} - pub struct HidDevice { inner: Box, } diff --git a/src/windows.rs b/src/windows.rs index ae1176a..7048f36 100644 --- a/src/windows.rs +++ b/src/windows.rs @@ -1,5 +1,5 @@ use crate::{HidDevice, HidResult}; -use windows_sys::core::GUID; +pub use windows_sys::core::GUID; impl HidDevice { /// Get the container ID for a HID device. diff --git a/src/windows_native/descriptor/mod.rs b/src/windows_native/descriptor/mod.rs index b5b70a8..a17a19f 100644 --- a/src/windows_native/descriptor/mod.rs +++ b/src/windows_native/descriptor/mod.rs @@ -4,7 +4,6 @@ mod tests; mod typedefs; mod types; -use crate::ensure; use crate::windows_native::descriptor::encoder::encode_descriptor; use crate::windows_native::descriptor::typedefs::{Caps, HidpPreparsedData, LinkCollectionNode}; use crate::windows_native::descriptor::types::{ diff --git a/src/windows_native/dev_node.rs b/src/windows_native/dev_node.rs index 07823c0..c7090a3 100644 --- a/src/windows_native/dev_node.rs +++ b/src/windows_native/dev_node.rs @@ -1,4 +1,3 @@ -use crate::ensure; use crate::windows_native::error::{check_config, WinError, WinResult}; use crate::windows_native::string::U16Str; use crate::windows_native::types::{DeviceProperty, PropertyKey}; diff --git a/src/windows_native/hid.rs b/src/windows_native/hid.rs index 2ca7801..2e1d273 100644 --- a/src/windows_native/hid.rs +++ b/src/windows_native/hid.rs @@ -1,4 +1,3 @@ -use crate::ensure; use crate::windows_native::error::{check_boolean, WinError, WinResult}; use crate::windows_native::types::Handle; use std::ffi::c_void; diff --git a/src/windows_native/interfaces.rs b/src/windows_native/interfaces.rs index 5bb00cd..ee4eb6b 100644 --- a/src/windows_native/interfaces.rs +++ b/src/windows_native/interfaces.rs @@ -1,4 +1,3 @@ -use crate::ensure; use crate::windows_native::error::{check_config, WinError, WinResult}; use crate::windows_native::hid::get_interface_guid; use crate::windows_native::string::{U16Str, U16StringList}; diff --git a/src/windows_native/mod.rs b/src/windows_native/mod.rs index 2ab24fe..cffbca2 100644 --- a/src/windows_native/mod.rs +++ b/src/windows_native/mod.rs @@ -1,4 +1,12 @@ -//! The implementation which uses the C library to perform operations +//! The implementation which uses the the raw win32 api to perform operations + +macro_rules! ensure { + ($cond:expr, $result:expr) => { + if !($cond) { + return $result; + } + }; +} mod descriptor; mod dev_node; @@ -42,15 +50,6 @@ use windows_sys::Win32::System::IO::{CancelIo, DeviceIoControl}; const STRING_BUF_LEN: usize = 128; -#[macro_export] -macro_rules! ensure { - ($cond:expr, $result:expr) => { - if !($cond) { - return $result; - } - }; -} - pub struct HidApiBackend; impl HidApiBackend { pub fn get_hid_device_info_vector(vid: u16, pid: u16) -> HidResult> { diff --git a/src/windows_native/types.rs b/src/windows_native/types.rs index eb7792b..2533223 100644 --- a/src/windows_native/types.rs +++ b/src/windows_native/types.rs @@ -1,5 +1,5 @@ use crate::windows_native::error::{WinError, WinResult}; -use crate::{ensure, BusType}; +use crate::BusType; use std::mem::{size_of, zeroed}; use std::ptr::null; use windows_sys::core::GUID;