Skip to content

Latest commit

 

History

History
95 lines (73 loc) · 4.62 KB

File metadata and controls

95 lines (73 loc) · 4.62 KB

Adding a native driver

Native drivers are a non-goal; see ADR 0004.

This page is the seam reference: the trait, the layers, the license rule, and the acceptance criteria. For the step-by-step bring-up (identify the device, scaffold a driver, decode its frames, open a pull request) follow Bringing up a sensor with fpdev. The fpdev workbench drives every phase offline.

The capture seam

A native, host-image sensor is expressed as one small async trait, FrameSource, in fprint-backend-native:

pub trait FrameSource {
    async fn capture(&mut self) -> Result<Capture>;   // the one poll boundary
    async fn arm(&mut self) -> Result<()> { Ok(()) }    // default no-op
    async fn disarm(&mut self) -> Result<()> { Ok(()) }
}

Your driver's whole job is to turn hardware into a grayscale Frame. Everything downstream is already built and verified:

  • ImageDevice<S: FrameSource> drives your source and is a complete fprint_core::Device (enroll / verify / identify).
  • detector runs fprint-mindtct (frame → minutiae) and matcher runs fprint-bozorth3 (minutiae → score). Both are golden bit-exact.

So a new driver is just a FrameSource — you do not touch fprint-core, the daemon, or the matcher.

Reference template

Three FrameSource implementors already exist to copy from:

  • SyntheticFrameSource and FileFrameSource — hardware-free.
  • UsbFrameSource — an experimental, hardware-unverified worked example for the Validity VFS5011, layered as proto (pure framing) → transport (the nusb seam) → source (the driver) → vfs5011 (device constants). Its protocol values are placeholders marked "HW-verified: required"; treat it as a shape to follow, not a working driver.

A good pattern is to keep protocol framing in pure, unit-tested Vec<u8> code and confine unsafe/nusb I/O to the transport leaf, exactly as usb/ does.

License discipline

This is the one hard rule for driver contributions (see ARCHITECTURE.md §Provenance & licensing):

  • Original code from interoperability facts is fine. VID/PID, endpoints, frame geometry, register names, and init sequences are facts, not copyrightable expression. Document them and write original Rust.
  • Transliterating a libfprint driver is not. A line-by-line port of LGPL driver code is a derivative work; it cannot be MIT OR Apache-2.0. If you genuinely port one, it must live in a separate LGPL-2.1-or-later crate, isolated from the permissive core, carrying its own SPDX header.

Acceptance criteria

  • #![forbid(unsafe_code)] holds, except in the transport leaf where the FFI/USB boundary genuinely needs it (quarantined, as nusb is today).
  • Every device value carries an HW-verified: marker recording whether hardware has vouched for it (see below); the pending ones are the bring-up's remaining work.
  • Verified black-box: golden fixtures, mock-transport tests, or captured-frame round-trips — the way sources/ and usb/mock_tests.rs are.
  • REUSE clean: every new file declares its license (inline SPDX for .rs, or the REUSE.toml bulk annotation), and mise run reuse passes.
  • Passes the workspace lints: cargo clippy --workspace --all-targets -- -D warnings and cargo fmt --all --check.

The HW-verified marker

A driver's device constants — VID/PID, endpoints, frame geometry, init/deinit sequences — are interoperability facts that only a physical sensor can confirm. Each one carries a marker in its doc-comment recording that state, on a single axis with two positions:

  • // HW-verified: requiredpending. A placeholder or an unconfirmed fact that no hardware has vouched for. This is what the scaffold emits.
  • // HW-verified: confirmed <evidence>resolved. Checked against hardware, with <evidence> recording how (a capture, a descriptor dump, a datasheet reference).

cargo xtask hw-checklist [driver] lists the pending markers, so a bring-up can see what is left to confirm. A bare HW-verified: required stays pending until someone confirms the value and writes the evidence in; nothing else changes its meaning.

Open a draft PR early — we're happy to help shape the seam with you.