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",
]