Skip to content

Commit

Permalink
feat: expand wdk-sys coverage to include spb-related headers
Browse files Browse the repository at this point in the history
  • Loading branch information
wmmc88 committed Jan 23, 2025
1 parent 5e50505 commit 972c00e
Show file tree
Hide file tree
Showing 13 changed files with 141 additions and 24 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"rust-analyzer.rustfmt.extraArgs": [
"+nightly"
"+nightly",
"--all"
],
"rust-analyzer.rustfmt.rangeFormatting.enable": true,
"evenBetterToml.formatter.crlf": true,
Expand Down
17 changes: 16 additions & 1 deletion crates/wdk-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ pub enum ApiSubset {
Wdf,
/// API subset for HID (Human Interface Device) drivers: <https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/_hid/>
Hid,
/// API subset required for SPB (Serial Peripheral Bus) drivers: <https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/_spb/>
Spb,
}

impl Default for Config {
Expand Down Expand Up @@ -643,7 +645,7 @@ impl Config {
match api_subset {
ApiSubset::Base => match &self.driver_config {
DriverConfig::Wdm | DriverConfig::Kmdf(_) => {
vec!["ntifs.h", "ntddk.h"]
vec!["ntifs.h", "ntddk.h", "ntstrsafe.h"]
}
DriverConfig::Umdf(_) => {
vec!["windows.h"]
Expand All @@ -667,6 +669,19 @@ impl Config {
hid_headers.extend(["HidSpiCx/1.0/hidspicx.h"]);
}

hid_headers
}
ApiSubset::Spb => {
let mut hid_headers = vec!["spb.h", "reshub.h"];

if let DriverConfig::Wdm | DriverConfig::Kmdf(_) = self.driver_config {
hid_headers.extend(["pwmutil.h"]);
}

if let DriverConfig::Kmdf(_) = self.driver_config {
hid_headers.extend(["spb/1.1/spbcx.h"]);
}

hid_headers
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/wdk-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ wdk-macros.workspace = true
default = []

hid = []
spb = []

nightly = ["wdk-macros/nightly"]
test-stubs = []
Expand Down
58 changes: 48 additions & 10 deletions crates/wdk-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ const BINDGEN_FILE_GENERATORS_TUPLES: &[(&str, GenerateFn)] = &[
("base.rs", generate_base),
("wdf.rs", generate_wdf),
("hid.rs", generate_hid),
("spb.rs", generate_spb),
];

fn initialize_tracing() -> Result<(), ParseError> {
Expand Down Expand Up @@ -223,6 +224,8 @@ fn generate_constants(out_path: &Path, config: &Config) -> Result<(), ConfigErro
ApiSubset::Wdf,
#[cfg(feature = "hid")]
ApiSubset::Hid,
#[cfg(feature = "spb")]
ApiSubset::Spb,
]);
trace!(header_contents = ?header_contents);

Expand All @@ -245,6 +248,8 @@ fn generate_types(out_path: &Path, config: &Config) -> Result<(), ConfigError> {
ApiSubset::Wdf,
#[cfg(feature = "hid")]
ApiSubset::Hid,
#[cfg(feature = "spb")]
ApiSubset::Spb,
]);
trace!(header_contents = ?header_contents);

Expand Down Expand Up @@ -295,10 +300,6 @@ fn generate_wdf(out_path: &Path, config: &Config) -> Result<(), ConfigError> {
.allowlist_file("(?i).*wdf.*");
trace!(bindgen_builder = ?bindgen_builder);

// As of NI WDK, this may generate an empty file due to no non-type and non-var
// items in the wdf headers(i.e. functions are all inlined). This step is
// intentionally left here in case older/newer WDKs have non-inlined functions
// or new WDKs may introduce non-inlined functions.
Ok(bindgen_builder
.generate()
.expect("Bindings should succeed to generate")
Expand All @@ -325,12 +326,11 @@ fn generate_hid(out_path: &Path, config: &Config) -> Result<(), ConfigError> {
.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)
{
builder = builder.allowlist_file(format!("(?i).*{header_file}.*"));
}

// 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
};
trace!(bindgen_builder = ?bindgen_builder);
Expand All @@ -349,6 +349,42 @@ fn generate_hid(out_path: &Path, config: &Config) -> Result<(), ConfigError> {
}
}

fn generate_spb(out_path: &Path, config: &Config) -> Result<(), ConfigError> {
cfg_if::cfg_if! {
if #[cfg(feature = "spb")] {
info!("Generating bindings to WDK: spb.rs");

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);

// 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
};
trace!(bindgen_builder = ?bindgen_builder);

Ok(bindgen_builder
.generate()
.expect("Bindings should succeed to generate")
.write_to_file(out_path.join("spb.rs"))?)
} 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");
Ok(())
}
}
}

/// Generates a `wdf_function_table.rs` file in `OUT_DIR` which contains the
/// definition of `WDF_FUNCTION_TABLE`. This is required to be generated here
/// since the size of the table is derived from either a global symbol
Expand Down Expand Up @@ -518,6 +554,8 @@ fn main() -> anyhow::Result<()> {
ApiSubset::Wdf,
#[cfg(feature = "hid")]
ApiSubset::Hid,
#[cfg(feature = "spb")]
ApiSubset::Spb,
])
.as_bytes(),
)?;
Expand Down
9 changes: 6 additions & 3 deletions crates/wdk-sys/src/hid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@
generate documentation for their bindings"
)]
mod bindings {
// allow wildcards for types module since underlying c code relies on all
// type definitions being in scope
#[allow(clippy::wildcard_imports)]
#[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"
)]
use crate::types::*;

include!(concat!(env!("OUT_DIR"), "/hid.rs"));
Expand Down
10 changes: 10 additions & 0 deletions crates/wdk-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,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 = "spb"
))]
pub mod spb;

#[cfg(feature = "test-stubs")]
pub mod test_stubs;

Expand Down
9 changes: 6 additions & 3 deletions crates/wdk-sys/src/ntddk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ pub use bindings::*;

#[allow(missing_docs)]
mod bindings {
// allow wildcards for types module since underlying c code relies on all
// type definitions being in scope
#[allow(clippy::wildcard_imports)]
#[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"
)]
use crate::types::*;

include!(concat!(env!("OUT_DIR"), "/ntddk.rs"));
Expand Down
37 changes: 37 additions & 0 deletions crates/wdk-sys/src/spb.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) Microsoft Corporation
// License: MIT OR Apache-2.0

//! Direct FFI bindings to SPB APIs from the Windows Driver Kit (WDK)
//!
//! This module contains all bindings to functions, constants, methods,
//! constructors and destructors in the following headers: `spb.h`, `spbcx.h`,
//! `reshub.h`, `pwmutil.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"), "/spb.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::*;
9 changes: 6 additions & 3 deletions crates/wdk-sys/src/wdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@ pub use bindings::*;
#[allow(missing_docs)]
#[allow(clippy::unreadable_literal)]
mod bindings {
// allow wildcards for types module since underlying c code relies on all
// type definitions being in scope
#[allow(clippy::wildcard_imports)]
#[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"
)]
use crate::types::*;

include!(concat!(env!("OUT_DIR"), "/wdf.rs"));
Expand Down
9 changes: 6 additions & 3 deletions crates/wdk-sys/src/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ pub use bindings::*;

#[allow(missing_docs)]
mod bindings {
// allow wildcards for types module since underlying c code relies on all
// type definitions being in scope
#[allow(clippy::wildcard_imports)]
#[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"
)]
use crate::types::*;

include!(concat!(env!("OUT_DIR"), "/windows.rs"));
Expand Down
1 change: 1 addition & 0 deletions examples/sample-kmdf-driver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ wdk-sys = { path = "../../crates/wdk-sys", version = "0.3.0" }
default = []

hid = ["wdk-sys/hid"]
spb = ["wdk-sys/spb"]

nightly = ["wdk/nightly", "wdk-sys/nightly"]

Expand Down
1 change: 1 addition & 0 deletions examples/sample-umdf-driver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ wdk-sys = { path = "../../crates/wdk-sys", version = "0.3.0" }
default = []

hid = ["wdk-sys/hid"]
spb = ["wdk-sys/spb"]

nightly = ["wdk/nightly", "wdk-sys/nightly"]

Expand Down
1 change: 1 addition & 0 deletions examples/sample-wdm-driver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ wdk-sys = { path = "../../crates/wdk-sys", version = "0.3.0" }
default = []

hid = ["wdk-sys/hid"]
spb = ["wdk-sys/spb"]

nightly = ["wdk/nightly", "wdk-sys/nightly"]

Expand Down

0 comments on commit 972c00e

Please sign in to comment.