diff --git a/crates/wdk-build/src/lib.rs b/crates/wdk-build/src/lib.rs index 13d676192..56b854368 100644 --- a/crates/wdk-build/src/lib.rs +++ b/crates/wdk-build/src/lib.rs @@ -197,8 +197,12 @@ pub enum ApiSubset { Base, /// API subset required for WDF (Windows Driver Framework) drivers: Wdf, + /// API subset for GPIO (General Purpose Input/Output) drivers: + Gpio, /// API subset for HID (Human Interface Device) drivers: Hid, + /// API subset for Parallel Ports drivers: + ParallelPorts, /// API subset for SPB (Serial Peripheral Bus) drivers: Spb, /// API subset for Storage drivers: @@ -660,6 +664,15 @@ impl Config { vec![] } } + ApiSubset::Gpio => { + let mut gpio_headers = vec!["gpio.h"]; + + if let DriverConfig::Kmdf(_) = self.driver_config { + gpio_headers.extend(["gpioclx.h"]); + } + + gpio_headers + } ApiSubset::Hid => { let mut hid_headers = vec!["hidclass.h", "hidsdi.h", "hidpi.h", "vhf.h"]; @@ -673,6 +686,15 @@ impl Config { hid_headers } + ApiSubset::ParallelPorts => { + let mut parallel_ports_headers = vec!["ntddpar.h", "ntddser.h"]; + + if let DriverConfig::Wdm | DriverConfig::Kmdf(_) = self.driver_config { + parallel_ports_headers.extend(["parallel.h"]); + } + + parallel_ports_headers + } ApiSubset::Spb => { let mut spb_headers = vec!["spb.h", "reshub.h"]; diff --git a/crates/wdk-sys/Cargo.toml b/crates/wdk-sys/Cargo.toml index 4533fc69a..30561d657 100644 --- a/crates/wdk-sys/Cargo.toml +++ b/crates/wdk-sys/Cargo.toml @@ -35,7 +35,9 @@ wdk-macros.workspace = true [features] default = [] +gpio = [] hid = [] +parallel-ports = ["gpio"] spb = [] storage = [] diff --git a/crates/wdk-sys/build.rs b/crates/wdk-sys/build.rs index a886d2df7..9bbc91915 100644 --- a/crates/wdk-sys/build.rs +++ b/crates/wdk-sys/build.rs @@ -131,7 +131,9 @@ const BINDGEN_FILE_GENERATORS_TUPLES: &[(&str, GenerateFn)] = &[ ("types.rs", generate_types), ("base.rs", generate_base), ("wdf.rs", generate_wdf), + ("gpio.rs", generate_gpio), ("hid.rs", generate_hid), + ("parallel_ports.rs", generate_parallel_ports), ("spb.rs", generate_spb), ("storage.rs", generate_storage), ]; @@ -196,8 +198,12 @@ fn generate_constants(out_path: &Path, config: &Config) -> Result<(), ConfigErro let header_contents = config.bindgen_header_contents([ ApiSubset::Base, ApiSubset::Wdf, + #[cfg(feature = "gpio")] + ApiSubset::Gpio, #[cfg(feature = "hid")] ApiSubset::Hid, + #[cfg(feature = "parallel-ports")] + ApiSubset::ParallelPorts, #[cfg(feature = "spb")] ApiSubset::Spb, #[cfg(feature = "storage")] @@ -222,8 +228,12 @@ fn generate_types(out_path: &Path, config: &Config) -> Result<(), ConfigError> { let header_contents = config.bindgen_header_contents([ ApiSubset::Base, ApiSubset::Wdf, + #[cfg(feature = "gpio")] + ApiSubset::Gpio, #[cfg(feature = "hid")] ApiSubset::Hid, + #[cfg(feature = "parallel-ports")] + ApiSubset::ParallelPorts, #[cfg(feature = "spb")] ApiSubset::Spb, #[cfg(feature = "storage")] @@ -291,22 +301,59 @@ fn generate_wdf(out_path: &Path, config: &Config) -> Result<(), ConfigError> { } } +fn generate_gpio(out_path: &Path, config: &Config) -> Result<(), ConfigError> { + cfg_if::cfg_if! { + if #[cfg(feature = "gpio")] { + info!("Generating bindings to WDK: gpio.rs"); + + let header_contents = + config.bindgen_header_contents([ApiSubset::Base, ApiSubset::Wdf, ApiSubset::Gpio]); + trace!(header_contents = ?header_contents); + + let bindgen_builder = { + let mut builder = bindgen::Builder::wdk_default(config)? + .with_codegen_config((CodegenConfig::TYPES | CodegenConfig::VARS).complement()) + .header_contents("gpio-input.h", &header_contents); + + // Only allowlist files in the gpio-specific files to avoid + // duplicate definitions + for header_file in config.headers(ApiSubset::Gpio) { + builder = builder.allowlist_file(format!("(?i).*{header_file}.*")); + } + builder + }; + trace!(bindgen_builder = ?bindgen_builder); + + Ok(bindgen_builder + .generate() + .expect("Bindings should succeed to generate") + .write_to_file(out_path.join("gpio.rs"))?) + } else { + let _ = (out_path, config); // Silence unused variable warnings when gpio feature is not enabled + + info!("Skipping gpio.rs generation since gpio feature is not enabled"); + Ok(()) + } + } +} + fn generate_hid(out_path: &Path, config: &Config) -> Result<(), ConfigError> { cfg_if::cfg_if! { if #[cfg(feature = "hid")] { info!("Generating bindings to WDK: hid.rs"); - let header_contents = config.bindgen_header_contents([ApiSubset::Base, ApiSubset::Wdf, ApiSubset::Hid]); + let header_contents = + config.bindgen_header_contents([ApiSubset::Base, ApiSubset::Wdf, ApiSubset::Hid]); trace!(header_contents = ?header_contents); let bindgen_builder = { - let mut builder = bindgen::Builder::wdk_default(config)? - .with_codegen_config((CodegenConfig::TYPES | CodegenConfig::VARS).complement()) - .header_contents("hid-input.h", &header_contents); + let mut builder = bindgen::Builder::wdk_default(config)? + .with_codegen_config((CodegenConfig::TYPES | CodegenConfig::VARS).complement()) + .header_contents("hid-input.h", &header_contents); - // Only allowlist files in the hid-specific files to avoid duplicate definitions - for header_file in config.headers(ApiSubset::Hid) - { + // Only allowlist files in the hid-specific files to avoid + // duplicate definitions + for header_file in config.headers(ApiSubset::Hid) { builder = builder.allowlist_file(format!("(?i).*{header_file}.*")); } builder @@ -320,8 +367,48 @@ fn generate_hid(out_path: &Path, config: &Config) -> Result<(), ConfigError> { } else { let _ = (out_path, config); // Silence unused variable warnings when hid feature is not enabled + info!("Skipping hid.rs generation since hid feature is not enabled"); + Ok(()) + } + } +} + +fn generate_parallel_ports(out_path: &Path, config: &Config) -> Result<(), ConfigError> { + cfg_if::cfg_if! { + if #[cfg(feature = "parallel-ports")] { + info!("Generating bindings to WDK: parallel_ports.rs"); + + let header_contents = config.bindgen_header_contents([ + ApiSubset::Base, + ApiSubset::Wdf, + ApiSubset::ParallelPorts, + ]); + trace!(header_contents = ?header_contents); + + let bindgen_builder = { + let mut builder = bindgen::Builder::wdk_default(config)? + .with_codegen_config((CodegenConfig::TYPES | CodegenConfig::VARS).complement()) + .header_contents("parallel-ports-input.h", &header_contents); + + // Only allowlist files in the parallel-ports-specific files to + // avoid duplicate definitions + for header_file in config.headers(ApiSubset::ParallelPorts) { + builder = builder.allowlist_file(format!("(?i).*{header_file}.*")); + } + builder + }; + trace!(bindgen_builder = ?bindgen_builder); + + Ok(bindgen_builder + .generate() + .expect("Bindings should succeed to generate") + .write_to_file(out_path.join("parallel_ports.rs"))?) + } else { + let _ = (out_path, config); // Silence unused variable warnings when parallel-ports feature is not enabled + info!( - "Skipping hid.rs generation since hid feature is not enabled"); + "Skipping parallel_ports.rs generation since parallel-ports feature is not enabled" + ); Ok(()) } } @@ -332,17 +419,18 @@ fn generate_spb(out_path: &Path, config: &Config) -> Result<(), ConfigError> { if #[cfg(feature = "spb")] { info!("Generating bindings to WDK: spb.rs"); - let header_contents = config.bindgen_header_contents([ApiSubset::Base, ApiSubset::Wdf, ApiSubset::Spb]); + let header_contents = + config.bindgen_header_contents([ApiSubset::Base, ApiSubset::Wdf, ApiSubset::Spb]); trace!(header_contents = ?header_contents); let bindgen_builder = { - let mut builder = bindgen::Builder::wdk_default(config)? - .with_codegen_config((CodegenConfig::TYPES | CodegenConfig::VARS).complement()) - .header_contents("spb-input.h", &header_contents); + let mut builder = bindgen::Builder::wdk_default(config)? + .with_codegen_config((CodegenConfig::TYPES | CodegenConfig::VARS).complement()) + .header_contents("spb-input.h", &header_contents); - // Only allowlist files in the spb-specific files to avoid duplicate definitions - for header_file in config.headers(ApiSubset::Spb) - { + // Only allowlist files in the spb-specific files to avoid + // duplicate definitions + for header_file in config.headers(ApiSubset::Spb) { builder = builder.allowlist_file(format!("(?i).*{header_file}.*")); } builder @@ -356,8 +444,7 @@ fn generate_spb(out_path: &Path, config: &Config) -> Result<(), ConfigError> { } else { let _ = (out_path, config); // Silence unused variable warnings when spb feature is not enabled - info!( - "Skipping spb.rs generation since spb feature is not enabled"); + info!("Skipping spb.rs generation since spb feature is not enabled"); Ok(()) } } diff --git a/crates/wdk-sys/src/gpio.rs b/crates/wdk-sys/src/gpio.rs new file mode 100644 index 000000000..0d0532523 --- /dev/null +++ b/crates/wdk-sys/src/gpio.rs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation +// License: MIT OR Apache-2.0 + +//! Direct FFI bindings to GPIO APIs from the Windows Driver Kit (WDK) +//! +//! This module contains all bindings to functions, constants, methods, +//! constructors and destructors in the following headers: `gpio.h`, +//! `gpioclx.h`. Types are not included in this module, but are available in the +//! top-level `wdk_sys` module. + +#[allow( + missing_docs, + reason = "most items in the WDK headers have no inline documentation, so bindgen is unable to \ + generate documentation for their bindings" +)] +mod bindings { + #[allow( + clippy::wildcard_imports, + reason = "the underlying c code relies on all type definitions being in scope, which \ + results in the bindgen generated code relying on the generated types being in \ + scope as well" + )] + #[allow( + unused_imports, + reason = "in certain versions of the WDK, there are no functions related to GPIO that can \ + be generated by bindgen, so these types are unused" + )] + use crate::types::*; + + include!(concat!(env!("OUT_DIR"), "/gpio.rs")); +} +#[allow( + unused_imports, + reason = "in certain versions of the WDK, there are no functions related to GPIO that can be \ + generated by bindgen, so the `bindings` module is empty" +)] +pub use bindings::*; diff --git a/crates/wdk-sys/src/lib.rs b/crates/wdk-sys/src/lib.rs index 4fbb3bb77..96c22abc4 100644 --- a/crates/wdk-sys/src/lib.rs +++ b/crates/wdk-sys/src/lib.rs @@ -23,11 +23,21 @@ pub use crate::{constants::*, types::*}; #[cfg(any(driver_model__driver_type = "WDM", driver_model__driver_type = "KMDF"))] pub mod ntddk; +#[cfg(driver_model__driver_type = "UMDF")] +pub mod windows; + #[cfg(any(driver_model__driver_type = "KMDF", driver_model__driver_type = "UMDF"))] pub mod wdf; -#[cfg(driver_model__driver_type = "UMDF")] -pub mod windows; +#[cfg(all( + any( + driver_model__driver_type = "WDM", + driver_model__driver_type = "KMDF", + driver_model__driver_type = "UMDF" + ), + feature = "gpio" +))] +pub mod gpio; #[cfg(all( any( @@ -39,6 +49,16 @@ pub mod windows; ))] pub mod hid; +#[cfg(all( + any( + driver_model__driver_type = "WDM", + driver_model__driver_type = "KMDF", + driver_model__driver_type = "UMDF" + ), + feature = "parallel-ports" +))] +pub mod parallel_ports; + #[cfg(all( any( driver_model__driver_type = "WDM", diff --git a/crates/wdk-sys/src/parallel_ports.rs b/crates/wdk-sys/src/parallel_ports.rs new file mode 100644 index 000000000..903f19b8f --- /dev/null +++ b/crates/wdk-sys/src/parallel_ports.rs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation +// License: MIT OR Apache-2.0 + +//! Direct FFI bindings to Parallel Ports APIs from the Windows Driver Kit (WDK) +//! +//! This module contains all bindings to functions, constants, methods, +//! constructors and destructors in the following headers: `ntddpar.h`, +//! `ntddser.h`, `parallel.h`. Types are not included in this module, but are +//! available in the top-level `wdk_sys` module. + +#[allow( + missing_docs, + reason = "most items in the WDK headers have no inline documentation, so bindgen is unable to \ + generate documentation for their bindings" +)] +mod bindings { + #[allow( + clippy::wildcard_imports, + reason = "the underlying c code relies on all type definitions being in scope, which \ + results in the bindgen generated code relying on the generated types being in \ + scope as well" + )] + #[allow( + unused_imports, + reason = "in certain versions of the WDK, there are no functions related to SPB that can \ + be generated by bindgen, so these types are unused" + )] + use crate::types::*; + + include!(concat!(env!("OUT_DIR"), "/parallel_ports.rs")); +} +#[allow( + unused_imports, + reason = "in certain versions of the WDK, there are no functions related to SPB that can be \ + generated by bindgen, so the `bindings` module is empty" +)] +pub use bindings::*; diff --git a/crates/wdk-sys/src/spb.rs b/crates/wdk-sys/src/spb.rs index 467e209f9..a8c862a42 100644 --- a/crates/wdk-sys/src/spb.rs +++ b/crates/wdk-sys/src/spb.rs @@ -23,7 +23,7 @@ mod bindings { #[allow( unused_imports, reason = "in certain versions of the WDK, there are no functions related to SPB that can \ - be generated by bindgen, so these types are unused " + be generated by bindgen, so these types are unused" )] use crate::types::*; diff --git a/examples/sample-kmdf-driver/Cargo.lock b/examples/sample-kmdf-driver/Cargo.lock index fc188719a..2c8511abe 100644 --- a/examples/sample-kmdf-driver/Cargo.lock +++ b/examples/sample-kmdf-driver/Cargo.lock @@ -402,9 +402,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] diff --git a/examples/sample-kmdf-driver/Cargo.toml b/examples/sample-kmdf-driver/Cargo.toml index 31d25dfa8..183078e20 100644 --- a/examples/sample-kmdf-driver/Cargo.toml +++ b/examples/sample-kmdf-driver/Cargo.toml @@ -32,7 +32,9 @@ wdk-sys = { path = "../../crates/wdk-sys", version = "0.3.0" } [features] default = [] +gpio = ["wdk-sys/gpio"] hid = ["wdk-sys/hid"] +parallel-ports = ["wdk-sys/parallel-ports"] spb = ["wdk-sys/spb"] storage = ["wdk-sys/storage"] diff --git a/examples/sample-umdf-driver/Cargo.lock b/examples/sample-umdf-driver/Cargo.lock index 1425eb7bb..d0fa8fefa 100644 --- a/examples/sample-umdf-driver/Cargo.lock +++ b/examples/sample-umdf-driver/Cargo.lock @@ -402,9 +402,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] diff --git a/examples/sample-umdf-driver/Cargo.toml b/examples/sample-umdf-driver/Cargo.toml index 58e6ad883..4602732e6 100644 --- a/examples/sample-umdf-driver/Cargo.toml +++ b/examples/sample-umdf-driver/Cargo.toml @@ -30,7 +30,9 @@ wdk-sys = { path = "../../crates/wdk-sys", version = "0.3.0" } [features] default = [] +gpio = ["wdk-sys/gpio"] hid = ["wdk-sys/hid"] +parallel-ports = ["wdk-sys/parallel-ports"] spb = ["wdk-sys/spb"] storage = ["wdk-sys/storage"] diff --git a/examples/sample-wdm-driver/Cargo.lock b/examples/sample-wdm-driver/Cargo.lock index b9ae07458..31e58e8c4 100644 --- a/examples/sample-wdm-driver/Cargo.lock +++ b/examples/sample-wdm-driver/Cargo.lock @@ -402,9 +402,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] diff --git a/examples/sample-wdm-driver/Cargo.toml b/examples/sample-wdm-driver/Cargo.toml index 461541425..c1f6e4bf9 100644 --- a/examples/sample-wdm-driver/Cargo.toml +++ b/examples/sample-wdm-driver/Cargo.toml @@ -30,7 +30,9 @@ wdk-sys = { path = "../../crates/wdk-sys", version = "0.3.0" } [features] default = [] +gpio = ["wdk-sys/gpio"] hid = ["wdk-sys/hid"] +parallel-ports = ["wdk-sys/parallel-ports"] spb = ["wdk-sys/spb"] storage = ["wdk-sys/storage"] diff --git a/tests/config-kmdf/Cargo.lock b/tests/config-kmdf/Cargo.lock index 225e1bff4..21915f499 100644 --- a/tests/config-kmdf/Cargo.lock +++ b/tests/config-kmdf/Cargo.lock @@ -485,9 +485,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] diff --git a/tests/config-umdf/Cargo.lock b/tests/config-umdf/Cargo.lock index 02d719e8e..f80eb0a50 100644 --- a/tests/config-umdf/Cargo.lock +++ b/tests/config-umdf/Cargo.lock @@ -485,9 +485,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] diff --git a/tests/mixed-package-kmdf-workspace/Cargo.lock b/tests/mixed-package-kmdf-workspace/Cargo.lock index 088eb5f5c..9f95b6fdb 100644 --- a/tests/mixed-package-kmdf-workspace/Cargo.lock +++ b/tests/mixed-package-kmdf-workspace/Cargo.lock @@ -417,9 +417,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] diff --git a/tests/umdf-driver-workspace/Cargo.lock b/tests/umdf-driver-workspace/Cargo.lock index 2da260d4e..07f864d9e 100644 --- a/tests/umdf-driver-workspace/Cargo.lock +++ b/tests/umdf-driver-workspace/Cargo.lock @@ -420,9 +420,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] diff --git a/tests/wdk-sys-tests/Cargo.lock b/tests/wdk-sys-tests/Cargo.lock index 30eb48935..6b4ae1165 100644 --- a/tests/wdk-sys-tests/Cargo.lock +++ b/tests/wdk-sys-tests/Cargo.lock @@ -402,9 +402,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ]