2026-04-04 18:38:10 -04:00
|
|
|
#!/usr/bin/python3
|
|
|
|
|
|
|
|
|
|
import traceback
|
|
|
|
|
import sys
|
|
|
|
|
import gi
|
|
|
|
|
|
|
|
|
|
gi.require_version('FPrint', '2.0')
|
2026-04-10 20:36:57 -04:00
|
|
|
from gi.repository import FPrint, GLib
|
2026-04-04 18:38:10 -04:00
|
|
|
|
|
|
|
|
# Exit with error on any exception, including those happening in callbacks
|
|
|
|
|
sys.excepthook = lambda *args: (traceback.print_exception(*args), sys.exit(1))
|
|
|
|
|
|
2026-04-10 20:36:57 -04:00
|
|
|
ctx = GLib.main_context_default()
|
|
|
|
|
|
2026-04-04 18:38:10 -04:00
|
|
|
c = FPrint.Context()
|
|
|
|
|
c.enumerate()
|
|
|
|
|
devices = c.get_devices()
|
|
|
|
|
|
|
|
|
|
assert len(devices) == 1, f"Expected 1 device, got {len(devices)}"
|
|
|
|
|
|
|
|
|
|
d = devices[0]
|
|
|
|
|
del devices
|
|
|
|
|
|
|
|
|
|
# Verify driver name
|
|
|
|
|
assert d.get_driver() == "validity", f"Expected 'validity', got '{d.get_driver()}'"
|
|
|
|
|
|
|
|
|
|
# Verify features detected by auto_initialize_features
|
|
|
|
|
assert not d.has_feature(FPrint.DeviceFeature.CAPTURE)
|
|
|
|
|
assert d.has_feature(FPrint.DeviceFeature.VERIFY)
|
|
|
|
|
assert d.has_feature(FPrint.DeviceFeature.IDENTIFY)
|
|
|
|
|
assert not d.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK)
|
validity: Iteration 6 — Enrollment, Verification, and DB Management
Add core fingerprint operations: enrollment, verification, identification,
print listing, print deletion, and storage clearing.
New files:
- validity_db.h/c: On-chip template database operations — command builders
for all DB commands (0x45-0x4B, 0x47-0x48, 0x51, 0x5E, 0x60, 0x62, 0x63,
0x64, 0x68, 0x69, 0x6B), response parsers for DB info/user storage/user/
record value/record children/new record ID, identity builder (UUID→VCSFW
binary), finger data builder, and db_write_enable blob accessor.
- validity_enroll.c: 31-state enrollment SSM with interrupt-driven finger
detection (EP 0x83), capture command orchestration via build_cmd_02(),
enrollment session management (create/update/commit), DB record creation
(user + finger), and LED glow feedback.
- validity_verify.c: 17-state verify/identify SSM with match command
dispatching (cmd 0x5E for verify, cmd 0x60 for identify), 6-state list
SSM for enumerating enrolled prints via GPtrArray, 8-state delete SSM,
and clear_storage stub.
Modified files:
- validity.h: Added DB header include, 5 new state enums (CalibState,
EnrollState, VerifyState, ListState, DeleteState), new struct fields
for enrollment/verification/list/delete state, function declarations.
- validity.c: Replaced all operation stubs with real implementations,
added cleanup for new fields in dev_close, wired all FpDevice methods.
- meson.build: Added 3 new source files to driver.
- tests/meson.build: Added test-validity-db executable.
- tests/validity/custom.py: Updated feature assertions (STORAGE,
STORAGE_LIST, STORAGE_CLEAR now enabled).
Tests: 29 new unit tests in test-validity-db.c covering all command
builders, response parsers, identity/finger data builders, and blob
accessor. All 37 tests pass (0 fail, 2 skip).
2026-04-06 00:51:35 -04:00
|
|
|
assert d.has_feature(FPrint.DeviceFeature.STORAGE)
|
|
|
|
|
assert d.has_feature(FPrint.DeviceFeature.STORAGE_LIST)
|
2026-04-04 18:38:10 -04:00
|
|
|
assert d.has_feature(FPrint.DeviceFeature.STORAGE_DELETE)
|
validity: Iteration 6 — Enrollment, Verification, and DB Management
Add core fingerprint operations: enrollment, verification, identification,
print listing, print deletion, and storage clearing.
New files:
- validity_db.h/c: On-chip template database operations — command builders
for all DB commands (0x45-0x4B, 0x47-0x48, 0x51, 0x5E, 0x60, 0x62, 0x63,
0x64, 0x68, 0x69, 0x6B), response parsers for DB info/user storage/user/
record value/record children/new record ID, identity builder (UUID→VCSFW
binary), finger data builder, and db_write_enable blob accessor.
- validity_enroll.c: 31-state enrollment SSM with interrupt-driven finger
detection (EP 0x83), capture command orchestration via build_cmd_02(),
enrollment session management (create/update/commit), DB record creation
(user + finger), and LED glow feedback.
- validity_verify.c: 17-state verify/identify SSM with match command
dispatching (cmd 0x5E for verify, cmd 0x60 for identify), 6-state list
SSM for enumerating enrolled prints via GPtrArray, 8-state delete SSM,
and clear_storage stub.
Modified files:
- validity.h: Added DB header include, 5 new state enums (CalibState,
EnrollState, VerifyState, ListState, DeleteState), new struct fields
for enrollment/verification/list/delete state, function declarations.
- validity.c: Replaced all operation stubs with real implementations,
added cleanup for new fields in dev_close, wired all FpDevice methods.
- meson.build: Added 3 new source files to driver.
- tests/meson.build: Added test-validity-db executable.
- tests/validity/custom.py: Updated feature assertions (STORAGE,
STORAGE_LIST, STORAGE_CLEAR now enabled).
Tests: 29 new unit tests in test-validity-db.c covering all command
builders, response parsers, identity/finger data builders, and blob
accessor. All 37 tests pass (0 fail, 2 skip).
2026-04-06 00:51:35 -04:00
|
|
|
assert d.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR)
|
2026-04-04 18:38:10 -04:00
|
|
|
assert d.has_feature(FPrint.DeviceFeature.ALWAYS_ON)
|
|
|
|
|
|
|
|
|
|
d.open_sync()
|
|
|
|
|
|
2026-04-10 20:36:57 -04:00
|
|
|
# 1. Clear storage — ensure the sensor is in a clean state
|
|
|
|
|
print("clearing storage")
|
|
|
|
|
d.clear_storage_sync()
|
|
|
|
|
print("clear done")
|
|
|
|
|
|
|
|
|
|
# 2. Enroll a finger
|
|
|
|
|
template = FPrint.Print.new(d)
|
|
|
|
|
|
|
|
|
|
def enroll_progress(*args):
|
|
|
|
|
print('enroll progress: ' + str(args))
|
|
|
|
|
|
|
|
|
|
print("enrolling")
|
|
|
|
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
|
|
|
|
p = d.enroll_sync(template, None, enroll_progress, None)
|
|
|
|
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
|
|
|
|
print("enroll done")
|
|
|
|
|
|
|
|
|
|
# 3. List enrolled prints — should have exactly one
|
|
|
|
|
print("listing")
|
|
|
|
|
stored = d.list_prints_sync()
|
|
|
|
|
print("listing done")
|
|
|
|
|
assert len(stored) == 1
|
|
|
|
|
|
|
|
|
|
# 4. Verify against the enrolled print
|
|
|
|
|
print("verifying")
|
|
|
|
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
|
|
|
|
verify_res, verify_print = d.verify_sync(p)
|
|
|
|
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
|
|
|
|
print("verify done")
|
|
|
|
|
del p
|
|
|
|
|
assert verify_res == True
|
|
|
|
|
|
|
|
|
|
# 5. Identify (async) with deserialized prints
|
|
|
|
|
identified = False
|
|
|
|
|
|
|
|
|
|
def identify_done(dev, res):
|
|
|
|
|
global identified
|
|
|
|
|
identified = True
|
|
|
|
|
identify_match, identify_print = dev.identify_finish(res)
|
|
|
|
|
print('identification done: ', identify_match, identify_print)
|
|
|
|
|
assert identify_match.equal(identify_print)
|
|
|
|
|
|
|
|
|
|
deserialized_prints = []
|
|
|
|
|
for p in stored:
|
|
|
|
|
deserialized_prints.append(FPrint.Print.deserialize(p.serialize()))
|
|
|
|
|
assert deserialized_prints[-1].equal(p)
|
|
|
|
|
del stored
|
|
|
|
|
|
|
|
|
|
print("async identifying")
|
|
|
|
|
d.identify(deserialized_prints, callback=identify_done)
|
|
|
|
|
del deserialized_prints
|
|
|
|
|
|
|
|
|
|
while not identified:
|
|
|
|
|
ctx.iteration(True)
|
|
|
|
|
|
|
|
|
|
# 6. Delete the enrolled print
|
|
|
|
|
print("deleting")
|
|
|
|
|
d.delete_print_sync(p)
|
|
|
|
|
print("delete done")
|
|
|
|
|
|
2026-04-04 18:38:10 -04:00
|
|
|
d.close_sync()
|
|
|
|
|
|
|
|
|
|
del d
|
|
|
|
|
del c
|