# fingerprintd Fingerprint daemon for the Fairphone 6 (`milos`, SM7635) on mainline Linux. `fingerprintd-core` is a static library with no GLib, no libqcomtee and no system headers. Everything in it is a wire format or a state machine that was recovered by reverse-engineering, so all of it is pinned by tests that run on a dev box with no phone, no TEE and no sensor. The daemon shell holds everything that touches hardware. ## Build ```sh crafter-build # bin/fingerprintd--/fingerprintd crafter-build test # the unit suites ``` Cross-compiling for the phone: ```sh packaging/make-sysroot.sh crafter-build -- --target=aarch64-alpine-linux-musl --sysroot=~/.cache/fingerprintd/sysroot-aarch64-alpine --march=armv8.6-a+fp16fml+aes+sha3+sm4 --mtune=cortex-a720 crafter-build test --target=aarch64-alpine-linux-musl --sysroot=~/.cache/fingerprintd/sysroot-aarch64-alpine --march=armv8.6-a+fp16fml+aes+sha3+sm4 --mtune=cortex-a720 ``` Verified on the device: all five suites pass cross-built and run on the phone itself, not only under emulation. ``` fprintd-enroll -f right-index-finger user ten stages, enroll-completed fprintd-list user - #0: right-index-finger fprintd-verify user (wrong finger) verify-no-match, on the first press fprintd-verify user (enrolled finger) verify-match, on the first press ``` ## Lock-screen unlock Two routes, both on by default: - **PAM.** The daemon provides `fprintd`, so a lock screen that runs `pam_fprintd` beside its password prompt unlocks by finger the usual way. Plasma's does (`kde-fingerprint`; the `fingerprint-auth` and `postlogin` services it needs are shipped here). Phosh's cannot: its PAM conversation answers every prompt with the password, so a fingerprint module in its stack would only stall the password behind the fingerprint timeout. - **Standby.** While the session in front on its seat is locked and the display is on, the daemon runs a verify of its own and answers a match with logind's `Session.Unlock`, which Phosh honours. No verify runs while the display is off (an open verify polls the sensor at ~5 Hz; the display state comes from the backlight's `bl_power` or the panel's DRM `dpms`, and a device with neither is treated as always on). Any fprintd client takes precedence: a `Claim` cancels the standby verify, a `Release` re-arms it. Only fingers named in that session owner's map unlock, and the map is re-read at every arm, so a finger deleted while locked stops counting at once. Per-finger `no-unlock` rules apply here too, and every match is announced as `FingerMatched` for the session agent. `--standby-unlock=off` disables it. ## Runtime dependencies The `focal64` trustlet is proprietary and is not in this repo. It is extracted from the device's own stock Android partition on first boot by the `fp6-vendor-blobs` mechanism, the same way other firmware in fp6-img is. ## Releases Every push to `main` is built and tested by CI, which then publishes the apks to the Forgejo Alpine registry that installed phones already point at. CI treats the registry's "already published" answer as nothing to do, so a push publishes only a package version new to the registry. The package version is `pkgver-rpkgrel`: `pkgver` is the `Version` constant in `interfaces/Fingerprintd.cppm`, `pkgrel` is the APKBUILD's and stays at 0. An installed phone picks a published version up with plain `apk upgrade`. From 0.2.6 on, a release is a range of commits ending in a bump commit titled `fingerprintd X.Y.Z` that changes only the version: the constant and the APKBUILD's `pkgver`. Each release is tagged `vX.Y.Z` on its bump commit (signed, annotated) with the release notes as the tag message, and published as a Forgejo release of the same name and text. No version before 0.2.6 has a tag or release notes. The notes are written for the people whose phones will upgrade: ``` fingerprintd X.Y.Z ## New - **What a user can now do.** One bullet per change, the most important first, with anything the user has to do inside the bullet. ## Fixes - **What went wrong, in the user's terms.** What they saw, what changes, what to do. ``` A section with nothing in it is left out, and so is behaviour the release does not change. Versioning, from 0.2.6 on, is `MAJOR.MINOR.PATCH`: the patch number counts releases, fixes and features alike; the minor number moves when a release changes what a user can rely on the daemon for; the major number moves when a release changes what an installed phone does without being asked. ## License GPL-3.0-only, see LICENSE. ## Copyright Copyright (C) 2026 Catcrafts® catcrafts.net