Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Native macOS backend #131

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,21 @@ jobs:
run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
- name: Build
run: cargo build --no-default-features --verbose
run: cargo build --no-default-features --features macos-hidapi --verbose
- name: Run tests
run: cargo test --no-default-features --verbose
run: cargo test --no-default-features --features macos-hidapi --verbose

build-macos-native:
runs-on: macos-latest
steps:
- name: checkout repository and submodules
uses: actions/checkout@v2
with:
submodules: recursive
- name: Install rust environment
run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
- name: Build
run: cargo build --no-default-features --features macos-native --verbose
- name: Run tests
run: cargo test --no-default-features --features macos-native --verbose
13 changes: 11 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ authors = [
"Artyom Pavlov <[email protected]>",
"mberndt123",
"niklasad1",
"Stefan Kerkmann"
"Stefan Kerkmann",
]
repository = "https://github.com/ruabmbua/hidapi-rs"
description = "Rust-y wrapper around hidapi"
Expand All @@ -19,7 +19,7 @@ documentation = "https://docs.rs/hidapi"
edition = "2021"

[features]
default = ["linux-static-hidraw", "illumos-static-libusb"]
default = ["linux-static-hidraw", "illumos-static-libusb", "macos-hidapi"]
linux-static-libusb = []
linux-static-hidraw = []
linux-shared-libusb = []
Expand All @@ -28,6 +28,8 @@ linux-native = ["dep:udev", "dep:nix"]
illumos-static-libusb = []
illumos-shared-libusb = []
macos-shared-device = []
macos-hidapi = []
macos-native = ["dep:core-foundation", "dep:mach2"]
windows-native = [
"windows-sys/Win32_Devices_DeviceAndDriverInstallation",
"windows-sys/Win32_Devices_HumanInterfaceDevice",
Expand All @@ -50,9 +52,16 @@ nix = { version = "0.26", optional = true }
[target.'cfg(windows)'.dependencies]
windows-sys = { version = "0.48", features = ["Win32_Foundation"] }

[target.'cfg(target_os = "macos")'.dependencies]
core-foundation = { version = "0.9.3", optional = true }
mach2 = { version = "0.4.1", optional = true }

[build-dependencies]
cc = "1.0"
pkg-config = "0.3"

[dev-dependencies]
pretty_env_logger = "0.5.0"

[package.metadata.docs.rs]
rustdoc-args = ["--cfg", "docsrs"]
44 changes: 35 additions & 9 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ fn main() {
} else if target.contains("illumos") {
compile_illumos();
} else {
panic!("Unsupported target os for hidapi-rs");
panic!("Unsupported target os {target} for hidapi-rs");
}
}

Expand Down Expand Up @@ -206,12 +206,38 @@ fn compile_windows() {
}

fn compile_macos() {
cc::Build::new()
.file("etc/hidapi/mac/hid.c")
.include("etc/hidapi/hidapi")
.compile("libhidapi.a");
println!("cargo:rustc-cfg=hidapi");
println!("cargo:rustc-link-lib=framework=IOKit");
println!("cargo:rustc-link-lib=framework=CoreFoundation");
println!("cargo:rustc-link-lib=framework=AppKit")
let avail_backends: [(&'static str, Box<dyn Fn()>); 2] = [
(
"MACOS_HIDAPI",
Box::new(|| {
cc::Build::new()
.file("etc/hidapi/mac/hid.c")
.include("etc/hidapi/hidapi")
.compile("libhidapi.a");
println!("cargo:rustc-cfg=hidapi");
println!("cargo:rustc-link-lib=framework=IOKit");
println!("cargo:rustc-link-lib=framework=CoreFoundation");
println!("cargo:rustc-link-lib=framework=AppKit")
}),
),
(
"MACOS_NATIVE",
Box::new(|| {
// The udev crate takes care of finding its library
println!("cargo:rustc-link-lib=framework=IOKit");
println!("cargo:rustc-link-lib=framework=CoreFoundation");
}),
),
];

let mut backends = avail_backends
.iter()
.filter(|f| env::var(format!("CARGO_FEATURE_{}", f.0)).is_ok());

if backends.clone().count() != 1 {
panic!("Exactly one macos hidapi backend must be selected.");
}

// Build it!
(backends.next().unwrap().1)();
}
25 changes: 19 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,20 @@ 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(all(target_os = "macos", hidapi))]
#[cfg_attr(docsrs, doc(cfg(target_os = "macos")))]
mod macos;
#[cfg(feature = "macos-native")]
mod macos_native;
#[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"))))]
#[cfg_attr(
docsrs,
doc(cfg(all(feature = "windows-native", target_os = "windows")))
)]
mod windows_native;

use libc::wchar_t;
Expand All @@ -98,6 +103,8 @@ pub use error::HidError;
use crate::hidapi::HidApiBackend;
#[cfg(all(feature = "linux-native", target_os = "linux"))]
use linux_native::HidApiBackend;
#[cfg(feature = "macos-native")]
use macos_native::HidApiBackend;
#[cfg(all(feature = "windows-native", target_os = "windows"))]
use windows_native::HidApiBackend;

Expand Down Expand Up @@ -131,7 +138,7 @@ fn lazy_init(do_enumerate: bool) -> HidResult<()> {
return Err(HidError::InitializationError);
}

#[cfg(all(target_os = "macos", feature = "macos-shared-device"))]
#[cfg(all(target_os = "macos", feature = "macos-shared-device", hidapi))]
unsafe {
ffi::macos::hid_darwin_set_open_exclusive(0)
}
Expand Down Expand Up @@ -267,7 +274,13 @@ impl HidApi {
#[derive(Clone, PartialEq)]
enum WcharString {
String(String),
#[cfg_attr(all(feature = "linux-native", target_os = "linux"), allow(dead_code))]
#[cfg_attr(
any(
all(feature = "linux-native", target_os = "linux"),
all(feature = "macos-native", target_os = "macos")
),
allow(dead_code)
)]
Raw(Vec<wchar_t>),
None,
}
Expand All @@ -283,7 +296,7 @@ impl From<WcharString> for Option<String> {

/// The underlying HID bus type.
#[repr(C)]
#[derive(Copy, Clone, Debug)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum BusType {
Unknown = 0x00,
Usb = 0x01,
Expand Down Expand Up @@ -575,7 +588,7 @@ impl HidDevice {
/// slice if there is no data to be read. In blocking mode, `read()` will
/// wait (block) until there is data to read before returning.
/// Modes can be changed at any time.
pub fn set_blocking_mode(&self, blocking: bool) -> HidResult<()> {
pub fn set_blocking_mode(&mut self, blocking: bool) -> HidResult<()> {
self.inner.set_blocking_mode(blocking)
}

Expand Down
Loading