# SPDX-License-Identifier: GPL-3.0-only # SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts® [Unit] Description=Fingerprint daemon (FocalTech FT9391 behind QTEE) Documentation=https://forgejo.catcrafts.net/Catcrafts/fingerprintd # The trustlet does the matching and it is a proprietary OEM-signed blob # extracted from the stock vendor partition, so it is not in this package. # Without it there is no sensor, and the unit stays out of the way instead of # restart-looping. ConditionPathExists=/usr/lib/firmware/focal64.mbn # /dev/tee0 is the qcomtee driver, which the pmOS kernel does not build yet # (CONFIG_QCOMTEE). modules-load.d asks for the module; this condition is what # makes the package harmless on a kernel that has none. ConditionPathExists=/dev/tee0 # The templates are QTEE containers on the Android persist partition, reached # through the SFS root's persist-data/root3 symlinks. RequiresMountsFor=/mnt/persist Requires=dbus.service # fp6-vendor-blobs reassembles the trustlet from the stock modem # partition; it runs in sysinit so this ordering already holds, and # saying so keeps the ConditionPathExists above from looking arbitrary. After=dbus.service fp6-vendor-blobs.service [Service] Type=simple # --edge-wake wait on the sensor IRQ instead of polling for a finger # --sfs-writable QTEE must be able to WRITE the template store, or an # enrolment cannot be saved. It can also unlink a container it # rejects, which is why it is opt-in rather than the default. # --rpmb-write the anti-rollback counter lives in RPMB; a save that cannot # write it does not commit. # No --verbose: it prints the frame-by-frame state machine, which on a phone # is both journal noise and a record of when its owner unlocked it. ExecStart=/usr/bin/fingerprintd --daemon --edge-wake \ --sfs-root=/var/lib/fingerprintd/sfs --sfs-writable --rpmb-write # Root is required and not reducible: the daemon drives the sensor rails over # gpiochip, holds /dev/tee0, and serves QTEE's RPMB transactions against the # raw UFS RPMB device. No sandboxing is declared here rather than declaring # some that was never tested against those three. Restart=on-failure RestartSec=5 # SIGTERM: the worker finishes the invoke it is inside before the session goes # down; QTEE's listener table is global to the boot and a half-torn session # leaves it holding ours. KillMode=mixed TimeoutStopSec=15 [Install] WantedBy=multi-user.target