Skip to content

Add support for sensor type 0xd51 (138a:00ab HP 840 G5, 06cb:00b7 HP G6)#256

Open
SimpleX-T wants to merge 9 commits into
uunicorn:masterfrom
SimpleX-T:feat/sensor-type-0xd51
Open

Add support for sensor type 0xd51 (138a:00ab HP 840 G5, 06cb:00b7 HP G6)#256
SimpleX-T wants to merge 9 commits into
uunicorn:masterfrom
SimpleX-T:feat/sensor-type-0xd51

Conversation

@SimpleX-T
Copy link
Copy Markdown

Summary

Adds support for sensor type 0xd51, which covers at least two USB IDs in the wild:

  • 138a:00ab — HP EliteBook 840 G5 (Synaptics "VFS7552 Touch with PurePrint")
  • 06cb:00b7 — HP G6-series laptops (Synaptics fingerprint reader [HP G6])

Verified working end-to-end on 138a:00ab (HP EliteBook 840 G5, Ubuntu 25.10): enrollment, verify (matches the correct finger, rejects others), and PAM-based sudo fingerprint auth. 06cb:00b7 is included by symmetry — same sensor type, same chip family — but I do not have that hardware to test on; would appreciate verification from the reporter of #225.

Closes #181 · Closes #225 · Closes #238

Why this is non-trivial (the missing piece)

Several users have previously tried the obvious patches — adding the PID to SupportedDevices, aliasing the crypto blob to blobs_97/blobs_9a, spoofing the sensor type to 0x199 — and consistently hit a wall where the service starts but fprintd-verify hangs forever or enroll-retry-scan loops indefinitely. Issue #225 documents exactly this flow.

The actual blocker is a protocol-level difference in interrupt delivery, not calibration or blobs:

The 0xd51 chip does not emit the b[0]=2 "finger detected" interrupt during a capture. It sends the start-ack (b[0]=0), and then jumps directly to b[0]=3 capture events. Sensor.capture()'s while True: if b[0]==2: break loop therefore hangs forever, even though everything else is working.

Once that loop is taught to also accept b[0]=3 (and pass the interrupt through to the next loop so it isn't lost), the rest of the existing pipeline — TLS-wrapped commands, image capture, the on-chip matcher, enrollment template accumulation — works correctly. The 0x199 alias for type, capture program, and calibration switch is enough for the matcher to accept real fingerprints and reject wrong ones.

What changed

File Change
validitysensor/usb.py Add DEV_AB = (0x138a, 0x00ab) and DEV_B7 = (0x06cb, 0x00b7) to SupportedDevices
validitysensor/blobs.py Route 0x00abblobs_97, 0x00b7blobs_9a. Verified accepted by the 0xd51 chip cleartext during init
validitysensor/firmware_tables.py Map both new IDs to HP's xpfwext filename (6_07f_hp_cmit_mis_qm.xpfwext, extracted from HP softpaq sp135736.exe). 0xd51 ships with firmware pre-loaded so upload_fwext returns early in normal use
validitysensor/sensor.py (a) Add 0xD51 to line_update_type1_devices. (b) In Sensor.open(), save the real device type and alias 0xd510x199 before downstream lookups (no native SensorTypeInfo/SensorCaptureProg exists for 0xd51). (c) In Sensor.capture(), accept b[0]=3 in the wait-for-finger loop only when the real device type is 0xd51, and pass the interrupt through to the wait-capture-complete loop so it isn't consumed twice
debian/python3-validity.udev Add 138a:00ab and 06cb:00b7 to the auto-start match block

Constraints and design choices

  • The interrupt-handling change is gated on self.real_device_type == 0xd51. Existing chips (0090/0097/9a/9d) take the unchanged code path. No behavioral change for users who aren't on this sensor type.
  • The 0x199 alias is a working compromise, not a perfect profile. A real SensorTypeInfo and SensorCaptureProg for 0xd51 would be better — extracting them from a Windows USB capture is the future work. Empirically the 0x199 profile produces images the on-chip matcher accepts; the 0xdb profile does not.
  • SensorTypeInfo for 0x199 is reused rather than introducing a new entry. The on-chip image processor uses the chip's own calibration; the wrong bytes_per_line is masked because matching happens on the chip side.
  • 0xd51 has no native SensorCaptureProg — the spoof lets the existing 0x199 program be reused. Comments in the code make this explicit so the future-correct fix is obvious.
  • No dev.reset() defensive patches in usb.py. Those were useful during development for recovering from unclean exits but shouldn't be on the normal-use path.

Test plan

Verified on Ubuntu 25.10 / kernel 6.17 / HP EliteBook 840 G5 (138a:00ab):

  • python3-validity.service reaches active (running) (previously failed at init_flash, sensor.open, or capture() depending on which patch combo was tried)
  • fprintd-enroll completes with real enroll-stage-passed events (not auto-completed fillers)
  • fprintd-verify returns verify-match for the enrolled finger
  • fprintd-verify returns verify-no-match for a different finger (proves the matcher actually distinguishes)
  • sudo -k && sudo whoami unlocks via fingerprint touch, no password
  • Captured image frames dumped via temporary logging show real fingerprint ridge data; enrollment templates (cmd6b responses) grow with each scan as features accumulate (5040 → 23304 bytes across 8 stages)

For 06cb:00b7: untested by me. The protocol-level fix is sensor-type-keyed and should apply, but matching specifically warrants verification from someone with the hardware.

Chip identification (for reference)

USB: 138a:00ab Validity Sensors, Inc. (HP EliteBook 840 G5)
Endpoints: 0x01 OUT bulk, 0x81/0x82 IN bulk, 0x83/0x84 IN interrupt (5 endpoints, vendor class)
identify_sensor name : "57K0 FM- 154-120"
device_info.type     : 0xd51
RomInfo              : timestamp=1415491824, build=164, major=6, minor=7, product=48
init_hardcoded blob  : blobs_97 (verified accepted, status 0000)
get_fw_info(2)       : returns valid partition info — firmware pre-loaded
TLS handshake        : ECDH P-256, succeeds against factory tls flash state

The 0xd51 chip does not emit the b[0]=2 "finger detected" interrupt
during capture, so the wait-finger loop in Sensor.capture() hangs
forever. Accept b[0]=3 as a substitute (gated on the real device
type so existing chips are unaffected) and pass the interrupt
through to the wait-capture-complete loop.

Also wires the two known USB IDs through SupportedDevices, blobs,
firmware_tables, the udev rule, and aliases sensor type 0xd51 to
the 0x199 profile so SensorTypeInfo / SensorCaptureProg lookups
succeed (no native profile exists yet).

Closes uunicorn#181
Closes uunicorn#225
Closes uunicorn#238
@DataConnection
Copy link
Copy Markdown

Thank you very much, @SimpleX-T! I was looking forward to use the fingerprint reader for 06cb:00b7 quite some time, and this looks promising!
Unfortunately it doesn't work out of the box - I get this error when running validity-sensors-firmware:

Traceback (most recent call last):
  File "/bin/validity-sensors-firmware", line 101, in <module>
    fwpath = download_and_extract_fw(dev_type, fwdir, fwuri=args.driver_uri)
  File "/bin/validity-sensors-firmware", line 39, in download_and_extract_fw
    fwuri = fwuri if fwuri else FIRMWARE_URIS[dev_type]['driver']
                                ~~~~~~~~~~~~~^^^^^^^^^^
KeyError: <SupportedDevices.DEV_B7: (1739, 183)>

Unfortunately I am unable to find the reason - my coding experience is not sufficient.

Without these entries `validity-sensors-firmware` crashes with a
KeyError for users on 138a:00ab and 06cb:00b7 who follow the README's
standard install flow. The 0xd51-family chips ship with firmware
pre-loaded so the downloader is only needed for factory-reset chips,
but the script should not crash.

Both PIDs point at HP softpaq sp135736.exe (the same blob extracted
to 6_07f_hp_cmit_mis_qm.xpfwext in FIRMWARE_NAMES). sha512 verified
against the canonical ftp.hp.com URL.

Reported by a 06cb:00b7 user on PR uunicorn#256.
@SimpleX-T
Copy link
Copy Markdown
Author

Hey @DataConnection, sorry, this is on me. When I added 06cb:00b7 to the supported devices list, I forgot to also add an entry to the firmware download table. That's exactly what that KeyError is telling us.

The good news: you almost certainly don't need to run validity-sensors-firmware at all. Your chip (the 0xd51-family one) ships with firmware already loaded from the factory. The downloader is only needed for factory-reset / unprovisioned chips. So just skip that step:

sudo systemctl restart python3-validity.service
fprintd-enroll
fprintd-verify

If fprintd-enroll asks you to swipe and fprintd-verify matches your finger, you're done — the firmware download wasn't needed.

If you hit a different error from that point on, paste the output and I'll take a look.

I pushed 20df336 to the PR branch - pulling the latest will give you a working validity-sensors-firmware too, in case you need it later.

SimpleX-T added 4 commits May 21, 2026 13:04
The chip's database rejects creating a second finger record with the
same subtype for the same user, which previously caused fprintd-enroll
to fail at the final stage with enroll-failed after all per-stage
captures had passed. Detect and delete any pre-existing record with the
same subtype right before db.new_finger.

Placing the delete here (inside do_create_finger, after all captures
have completed) rather than at EnrollStart matters: pre-deleting before
the enrollment session starts left the chip in a state where every
subsequent capture returned retry-scan indefinitely until the daemon
was restarted. By the time do_create_finger runs the captures are done
and the chip is ready to accept the save, so deletion at this point
doesn't disrupt session state.
Lenovo softpaqs (the previously supported devices) ship as Inno Setup
installers, which is what innoextract handles. HP softpaqs (sp135736.exe
used for the new DEV_AB and DEV_B7 entries) are CAB-wrapped self-
extracting exes — innoextract rejects them with "Not a supported Inno
Setup installer!" and the postinst surfaces a noisy Python traceback.

Try innoextract first; on CalledProcessError or FileNotFoundError, fall
back to cabextract. The standalone tool-availability check accepts
either extractor so installations on either family work out of the box.

Note: dropped the `-F <fwname>` filter from cabextract — its pattern
matches the full path inside the cab (e.g. src/driver/INF/x64/6_07f_...
xpfwext) not just the basename, so -F would silently skip the target.
Extract everything; the existing `find` afterward locates the file
regardless of the subdirectory it landed in.
debian/python3-validity.postinst: run pam-auth-update --package --enable
fprintd so sudo / screen-unlock / GNOME Settings fingerprint flows work
immediately after install, without the user having to know about
pam-auth-update.

debian/control: recommend libpam-fprintd (the PAM module our postinst
enables) and cabextract (the fallback extractor used by the new
validity-sensors-firmware path for HP softpaqs).

Bumped changelog through 0.16~hp1/hp2/hp3, with hp3 documenting the
same-finger re-enroll fix shipped this release.
pam_fprintd re-prints "Place your finger on the reader" for every
verify-retry-scan signal it receives. On the 0xd51 chip the capture
loop is chatty — a single 10-second verify window can fire the signal
20+ times, flooding the terminal during sudo authentication.

Suppress all but the first verify-retry-scan per VerifyStart so the
user sees one initial prompt and one early "place again" hint, then
silence until match or timeout. Enrollment behavior is unchanged
because per-stage retry hints are useful there (each stage is a
discrete user action where lift-and-retry feedback matters).
@DataConnection
Copy link
Copy Markdown

Thanks a lot for your effort and the additional commits - now it installs flawlessly (despite showing one error when running validity-sensors-firmware:

# validity-sensors-firmware 
Downloading https://ftp.hp.com/pub/softpaq/sp135501-136000/sp135736.exe to extract 6_07f_hp_cmit_mis_qm.xpfwext
Done with 1 error.
Found firmware at /tmp/tmp8n2xqp6t/src/driver/INF/x64/6_07f_hp_cmit_mis_qm.xpfwext

# ls -la /var/run/python-validity/
insgesamt 216
drwxr-xr-x  2 root root     80 21. Mai 17:43 .
drwxr-xr-x 44 root root    960 21. Mai 17:42 ..
-rw-r--r--  1 root root 216973 21. Mai 17:44 6_07f_hp_cmit_mis_qm.xpfwext
-rw-r--r--  1 root root     72 21. Mai 17:42 backoff

But starting python3-validity.service fails:


Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:>cmd> 3e
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:<cmd< 0000ef004000001001000001010005000104070000100000001000000201020000200000005005000606030000700500008000000302170000f0050000f004000403050000e00a0000200500
Mai 21 17:42:23 monstar python3[38905]: INFO:root:Flash has 5 partitions.
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:>cmd> 01
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:<cmd< 0000f0b05e54a40000000607013000010000b00d48c86dd80023000000000100000003d10007
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:>cmd> 19
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:<cmd< 000002002100100100000000000000000000000075a60c5e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:>cmd> 4302
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:<cmd< 0000010002000800a558265e0100344602000700d03c00000100840801000700800600000200842803001200701000000200763601000c00000a00000100864700000100505a00000200237700000100c02f00000>
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:>cmd> 06020000014a231406e5542fc6dc3b1aedebe68f55596ad3ca13f6e019994c6f71672fff756fbde0511d09d45978b12ba415b3694a0e76348c8cfe9dbb9abf86813fc0c67c1005519a6f87360c2fb3e12bd0a9e01>
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:<cmd< 0000
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:>cmd> 40010100000000000000100000
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:<cmd< 0000001000000000000001006e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d000400a10030b14a20d3c19fcfc5a7f3bedb1ff6fbb9c82b44155f7dc3d6de0300a30023a6026b385>
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:block id 0000 (1 bytes)
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:block id 0004 (161 bytes)
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:Private key:
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:x=0xfc54faebebce6dd7e6c0a7fc62243cf64c4db896369a959c1e28c6b2d7b96083
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:y=0x10244b044f3d053d6f269b88a0975ec9110d993ba511e4a14864ec16741dfd08
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:d=0x448339900fb96ff97c5af985ee063d36b158e20d75ee36e21177f66be15def06
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:block id 0003 (184 bytes)
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:TLS cert blob: b'17000000200000008360b9d7b2c6281e9c959a3696b84d4cf63c2462fca7c0e6d76dceebebfa54fc00000000000000000000000000000000000000000000000000000000000000000000000008fd1d>
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:block id 0005 (420 bytes)
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:unhandled block id 0005 (420 bytes): b'170000000001000001000000fcffffffffffffffffffffff00000000000000000000000001000000ffffffff000000000000000000000000000000000000000000000000>
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:block id 0001 (256 bytes)
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:block id 0002 (256 bytes)
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:block id 0006 (400 bytes)
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:ECDH params:
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:x=0x79a81bae246821dcef190879aa21440302da3c6b50187f4dfe11f71fc6c1d299
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:y=0xcd52fde145924a11f2bb63c112ab14749956fee81302a3d7fe5f4053e20933a7
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:>cmd> 440000001603030045010000410303e6094fe662a9457ce3865895fc1a5895bf1403507e49aac38c28758a5a555bcd07000000000000000006c005003d008d00000a000400020017000b00020100
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:<cmd< 160303003d0200002d0303606956f090a77aaa7990e0359a10b506808cfc4623391da7840c1a5cc6f8d02b07544c5390a77aaac005000d000004014000000e000000
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:>tls> 16: 1400000c50f089f919149d8f0b29b4b5
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:>cmd> 4400000016030301540b0000c00000b80000b8ac1617000000200000008360b9d7b2c6281e9c959a3696b84d4cf63c2462fca7c0e6d76dceebebfa54fc00000000000000000000000000000000000000000000000>
Mai 21 17:42:23 monstar systemd[1]: Reloaded D-Bus System Message Bus.
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:<cmd< 1403030001011603030050c01085ff0098a726b6df8b39fef38e9a8f1599f64b3d02d74a4b1e53b38de5b14e65202924a02c6cf6826ff982c172d9f50d18474efecf5c08727f636ffb1f7454535853dd68ea8eb70>
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:<tls< 16: 1400000ceee4a374e4cb18f940eba896
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:>tls> 17: 4302
Mai 21 17:42:23 monstar python3[38905]: DEBUG:root:>cmd> 170303004006c3b771504bdf7f0d028aaea633f5e569271df2b0a4e19d75d289d3ab23dfa312bad972a8423857a624ae250fe1015bfe988d7f4e012a60a17202a4fa01f829
Mai 21 17:42:24 monstar python3[38905]: DEBUG:root:<cmd< 17030300a09a886bc438ddf20ff24cd324f7bcb19d5d0b221f71cde3e0d927fa9239eb577f0b7dc103ce4a237aa1b103750b4ccca3aacc163e60bf4291f11674e09cb227b6403293227cf2616190eccaa22e11d42>
Mai 21 17:42:24 monstar python3[38905]: DEBUG:root:<tls< 17: 0000010002000800a558265e0100344602000700d03c00000100840801000700800600000200842803001200701000000200763601000c00000a00000100864700000100505a00000200237700000100c02f0>
Mai 21 17:42:24 monstar python3[38905]: INFO:root:Detected firmware version 1.2 (Tue Jan 21 02:49:25 2020))
Mai 21 17:42:24 monstar python3[38905]: DEBUG:root:>tls> 17: 75
Mai 21 17:42:24 monstar python3[38905]: DEBUG:root:>cmd> 170303004063b20803e1bbaf4361bcdbe42ccdf809b92dabc5e13f45e54c995a4d225723849075d94875d6569ce22b4fb8b78e58f6101995867f8d1f92835b33cca21724dc
Mai 21 17:42:24 monstar python3[38905]: DEBUG:root:<cmd< 170303004031342ecab785767e736b3000fbc56e51f76520470bbd99abbe2109d63ebfcb239dce6a6f8a050c5fe6fed46c703c701ec7e462d42dc034cfa81644b4a6e6604c
Mai 21 17:42:24 monstar python3[38905]: DEBUG:root:<tls< 17: 00000000000085009001
Mai 21 17:42:24 monstar python3[38905]: INFO:root:Opening sensor: 57K0 FM-3439-002
Mai 21 17:42:24 monstar dbus-service[38905]: Traceback (most recent call last):
Mai 21 17:42:24 monstar dbus-service[38905]:   File "/usr/lib/python-validity/dbus-service", line 316, in <module>
Mai 21 17:42:24 monstar dbus-service[38905]:     main()
Mai 21 17:42:24 monstar dbus-service[38905]:     ~~~~^^
Mai 21 17:42:24 monstar dbus-service[38905]:   File "/usr/lib/python-validity/dbus-service", line 273, in main
Mai 21 17:42:24 monstar dbus-service[38905]:     init.open()
Mai 21 17:42:24 monstar dbus-service[38905]:     ~~~~~~~~~^^
Mai 21 17:42:24 monstar dbus-service[38905]:   File "/usr/lib/python3.14/site-packages/validitysensor/init.py", line 50, in open
Mai 21 17:42:24 monstar dbus-service[38905]:     open_common()
Mai 21 17:42:24 monstar dbus-service[38905]:     ~~~~~~~~~~~^^
Mai 21 17:42:24 monstar dbus-service[38905]:   File "/usr/lib/python3.14/site-packages/validitysensor/init.py", line 36, in open_common
Mai 21 17:42:24 monstar dbus-service[38905]:     sensor.open()
Mai 21 17:42:24 monstar dbus-service[38905]:     ~~~~~~~~~~~^^
Mai 21 17:42:24 monstar dbus-service[38905]:   File "/usr/lib/python3.14/site-packages/validitysensor/sensor.py", line 252, in open
Mai 21 17:42:24 monstar dbus-service[38905]:     raise Exception('Device %s is not supported (sensor type 0x%x)' %
Mai 21 17:42:24 monstar dbus-service[38905]:                     (self.device_info.name, self.device_info.type))
Mai 21 17:42:24 monstar dbus-service[38905]: Exception: Device 57K0 FM-3439-002    is not supported (sensor type 0x969)
Mai 21 17:42:24 monstar systemd[1]: python3-validity.service: Main process exited, code=exited, status=1/FAILURE
Mai 21 17:42:24 monstar systemd[1]: python3-validity.service: Failed with result 'exit-code'.
Mai 21 17:42:24 monstar systemd[1]: python3-validity.service: Scheduled restart job, restart counter is at 4.
Mai 21 17:42:24 monstar systemd[1]: python3-validity.service: Start request repeated too quickly.
Mai 21 17:42:24 monstar systemd[1]: python3-validity.service: Failed with result 'start-limit-hit'.
Mai 21 17:42:24 monstar systemd[1]: Failed to start python-validity driver dbus service.

USB devices:


# lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 0408:5373 Quanta Computer, Inc. HP HD Camera
Bus 001 Device 003: ID 06cb:00b7 Synaptics, Inc. Fingerprint reader [HP G6]
Bus 001 Device 004: ID 8087:0029 Intel Corp. AX200 Bluetooth
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 005 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 006 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub

Any ideas? I'm stuck.

@SimpleX-T
Copy link
Copy Markdown
Author

Hi @DataConnection, I have been working on this fix, and I have come up with an easier way to implement it. You can now pull it from the apt store:

sudo add-apt-repository ppa:devtochukwu/fingerprint
sudo apt install python3-validity

Let me know if this works

SimpleX-T added 2 commits May 21, 2026 19:30
debian/source/options: tar-ignore .pybuild, build, *.egg-info,
__pycache__, *.pyc.

3.0 (native) source packages bundle the working tree verbatim, so
any leftover pybuild cache from prior local debuild runs gets shipped
to Launchpad. pybuild's cached state embeds the developer's absolute
paths (e.g. /home/<dev>/.../python-validity/.pybuild/...), which the
build chroot can't write to. The first per-series build succeeded
because pybuild created the cache fresh; subsequent series builds
inherited the dirty cache and failed with Permission denied trying
to write into the baked-in path.

This is a packaging-only change; no source code differs.
sensor.py: log resolved capture geometry once at chip open. Useful
when investigating whether the 0x199 spoof produces appropriate
dimensions for whatever chip the daemon is talking to. The log line
includes real_type vs spoofed_type, lines_2d from the capture
program, computed lines_per_frame, bytes_per_line, line_width, and
lines_per_calibration_data — everything needed to recognize a
profile mismatch without re-instrumenting.

dbus-service: in VerifyStart, log every internal chip retry-scan to
the journal independent of the D-Bus signal throttle. Lets users
and support tickets quantify capture quality without manual
instrumentation — `journalctl -u python3-validity.service | grep
'Chip capture retry-scan'` gives the raw count immediately.

Both changes are INFO-level log lines, no functional impact. About
1 log per chip open + 0-3 lines per verify in normal use.
@mpsijm
Copy link
Copy Markdown

mpsijm commented May 24, 2026

Hi @SimpleX-T, thank you so much for working on this! I never thought I'd still be able to use the fingerprint scanner on my 6½-year-old HP ZBook Studio G5 😄 It does not work for me yet, but hopefully we can help each other debug the issue!

According to lsusb, my laptop has scanner ID 138a:00ab Validity Sensors, Inc.

I installed your branch by patching the PKGBUILD from the AUR as follows:
diff --git a/PKGBUILD b/PKGBUILD
index ad31986..d1378b1 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -2,7 +2,7 @@
 # Contributor: j.r <j.r@jugendhacker.de>
 # Contributor: Matthew Murray <matt@mattmurr.xyz>
 pkgname=python-validity
-pkgver=0.15
+pkgver=0.15+0xd51
 pkgrel=1
 pkgdesc="Validity fingerprint sensor driver"
 arch=(any)
@@ -12,22 +12,22 @@ depends=(python python-yaml python-pyusb python-cryptography python-dbus python-
 makedepends=(python-setuptools glib2-devel)
 conflicts=($pkgname)
 provides=($pkgname)
-url="https://github.com/uunicorn/${pkgname}"
+url="https://github.com/SimpleX-T/${pkgname}"
 source=(
-  "$pkgname-$pkgver.tar.gz::${url}/archive/${pkgver}.tar.gz"
+  "$pkgname-$pkgver.tar.gz::${url}/archive/refs/heads/feat/sensor-type-0xd51.tar.gz"
   python3-validity-suspend-hotfix.service 
 )
-md5sums=('7134839860dea1caafa5ae5024536385'
+md5sums=('SKIP'
          'cf8c944df027bbb349c56710c9755cbe')
 install=$pkgname.install
 
 build() {
-  cd $srcdir/$pkgname-$pkgver
+  cd $srcdir/$pkgname-feat-sensor-type-0xd51
   python setup.py build
 }
 
 package() {
-  cd $srcdir/$pkgname-$pkgver
+  cd $srcdir/$pkgname-feat-sensor-type-0xd51
   python setup.py install --prefix=/usr --root $pkgdir || return 1
 
   sed -i 's/^Restart=.*/Restart=on-failure/' debian/python3-validity.service

Then, I ran makepkg and pacman -U python-validity-0.15+0xd51-1-any.pkg.tar.zst. Just to be sure, I verified that the contents of /usr/bin/validity-sensor-firmware, /usr/lib/python3.14/site-packages/validitysensor, etc. are indeed the same as on your branch.

However, both fprintd-enroll and sudo fprintd-enroll -f right-index-finger $USER fail with exit code 1, printing only list_devices failed:. I have also followed the steps at https://github.com/uunicorn/python-validity#error-situations, but that did not help either.

Logs from these "Error situations" commands:

Logs from sudo journalctl -u python3-validity -b (the service kept rebooting itself every 15 seconds, so simply running sudo systemctl status python3-validity wasn't helpful):

May 24 13:18:22 maarten-zbook-g5 systemd[1]: python3-validity.service: Scheduled restart job, restart counter is at 13.
May 24 13:18:22 maarten-zbook-g5 systemd[1]: Started python-validity driver dbus service.
May 24 13:18:22 maarten-zbook-g5 python3[164883]: DEBUG:root:>cmd> 3e
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]: Traceback (most recent call last):
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:   File "/usr/lib/python-validity/dbus-service", line 324, in <module>
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:     main()
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:     ~~~~^^
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:   File "/usr/lib/python-validity/dbus-service", line 281, in main
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:     init.open()
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:     ~~~~~~~~~^^
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:   File "/usr/lib/python3.14/site-packages/validitysensor/init.py", line 50, in open
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:     open_common()
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:     ~~~~~~~~~~~^^
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:   File "/usr/lib/python3.14/site-packages/validitysensor/init.py", line 31, in open_common
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:     init_flash()
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:     ~~~~~~~~~~^^
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:   File "/usr/lib/python3.14/site-packages/validitysensor/init_flash.py", line 122, in init_flash
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:     info = get_flash_info()
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:   File "/usr/lib/python3.14/site-packages/validitysensor/flash.py", line 40, in get_flash_info
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:     rsp = tls.cmd(unhex('3e'))
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:   File "/usr/lib/python3.14/site-packages/validitysensor/tls.py", line 124, in cmd
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:     rsp = self.usb.cmd(cmd)
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:   File "/usr/lib/python3.14/site-packages/validitysensor/usb.py", line 106, in cmd
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:     self.dev.write(1, out)
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:     ~~~~~~~~~~~~~~^^^^^^^^
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:   File "/usr/lib/python3.14/site-packages/usb/core.py", line 1003, in write
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:     return fn(
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:             self._ctx.handle,
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:     ...<3 lines>...
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:             self.__get_timeout(timeout)
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:         )
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:   File "/usr/lib/python3.14/site-packages/usb/backend/libusb1.py", line 841, in bulk_write
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:     return self.__write(self.lib.libusb_bulk_transfer,
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:            ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:                         dev_handle,
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:                         ^^^^^^^^^^^
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:     ...<2 lines>...
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:                         data,
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:                         ^^^^^
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:                         timeout)
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:                         ^^^^^^^^
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:   File "/usr/lib/python3.14/site-packages/usb/backend/libusb1.py", line 942, in __write
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:     _check(retval)
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:     ~~~~~~^^^^^^^^
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:   File "/usr/lib/python3.14/site-packages/usb/backend/libusb1.py", line 602, in _check
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]:     raise USBTimeoutError(_strerror(ret), ret, _libusb_errno[ret])
May 24 13:18:37 maarten-zbook-g5 dbus-service[164883]: usb.core.USBTimeoutError: [Errno 110] Operation timed out
May 24 13:18:37 maarten-zbook-g5 systemd[1]: python3-validity.service: Main process exited, code=exited, status=1/FAILURE
May 24 13:18:37 maarten-zbook-g5 systemd[1]: python3-validity.service: Failed with result 'exit-code'.

After stopping the service, I tried:

$ sudo validity-sensors-firmware
Downloading https://ftp.hp.com/pub/softpaq/sp135501-136000/sp135736.exe to extract 6_07f_hp_cmit_mis_qm.xpfwext
Done with 1 error.
Found firmware at /tmp/tmpghvxw95v/src/driver/INF/x64/6_07f_hp_cmit_mis_qm.xpfwext
$ sudo python3 /usr/share/python-validity/playground/factory-reset.py
Traceback (most recent call last):
  File "/usr/share/python-validity/playground/factory-reset.py", line 6, in <module>
    factory_reset()
    ~~~~~~~~~~~~~^^
  File "/usr/lib/python3.14/site-packages/validitysensor/sensor.py", line 87, in factory_reset
    assert_status(usb.cmd(reset_blob))
    ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.14/site-packages/validitysensor/util.py", line 12, in assert_status
    raise Exception('Failed: %04x' % s)
Exception: Failed: 0401

If there's anything else I can do to debug or gather more information, let me know 🙂

Multiple users reported the 0xd51-family chips (138a:00ab, 06cb:00b7)
getting stuck after cold boot, unclean exit, or suspend/resume — the
chip accepts the bulk-OUT but never responds on bulk-IN, so the first
cleartext cmd (cmd 3e get_flash_info) times out and the daemon
restart-loops every 15 seconds. The workaround users were running
manually is a USB-level reset:

    sudo systemctl stop python3-validity open-fprintd
    sudo udevadm trigger --attr-match=idVendor=138a --attr-match=idProduct=00ab
    sudo systemctl start python3-validity open-fprintd

The reset call here is the in-driver equivalent. The chip's USB
address can shift after reset, so we re-find by vid/pid.

Reported by Killersparrow1 (issue uunicorn#238, Fedora 44, sensor vanishes
on reboot) and a separate Arch / ZBook G5 user (USBTimeoutError on
cmd 3e). The patch matches what the project memory has flagged for
the past two sessions as "kept local and not in PR" — turns out it
was the actually-load-bearing piece.

Locally confirmed: clean daemon restart, sudo matches in 1 retry,
no traceback, no "USB reset failed" warning.
@SimpleX-T
Copy link
Copy Markdown
Author

Hi @mpsijm — sorry for the slow reply. That USBTimeoutError on the very first cmd 3e is the chip stuck in a TLS-pending state from a previous boot or unclean exit — the bulk-OUT goes through but the chip never replies on bulk-IN, so get_flash_info() times out and the daemon restart-loops every 15s.

Just pushed cd0def0 to the branch, which fixes it: a defensive USB reset at the start of Usb.open_dev(). Same effect as a manual udevadm trigger --attr-match=idVendor=138a --attr-match=idProduct=00ab, but built into the driver so it runs every time the daemon opens the chip.

To update on Arch via your patched AUR PKGBUILD: since you have md5sums=('SKIP' ...) and the source pointing at refs/heads/feat/sensor-type-0xd51.tar.gz, just rerun makepkg -f and pacman -U python-validity-0.15+0xd51-1-any.pkg.tar.zst. It'll pull the latest branch tip. Then sudo systemctl restart python3-validity.service.

Re your factory-reset.py returning Failed: 0401 — that's the chip refusing the reset because it's already in a clean factory state. You don't actually need to factory-reset on a fresh install; that script is only for recovering from a corrupted enrollment session.

Let me know how the rebuild goes!

@mpsijm
Copy link
Copy Markdown

mpsijm commented May 25, 2026

No need to apologize for inherently asynchronous communication! You already reply faster than most people do on open-source repositories 😄

Long ago, I used the fingerprint scanner on Windows (dual-boot). Haven't switched back to Windows in years, but no clue if the unclean exit could be caused by this. At least good to hear that the error I receive on factory reset is not actually an error 😂

Note that skipping the md5sum check does not automatically trigger a re-download, but deleting the previous source .tar.gz works 🙂 After reinstalling, Pacman automatically restarts the service, and I now receive different errors (after which the service restarts itself five times before giving up). So, your defensive USB reset appears to have effect, thanks for that fix! 🎉

Excerpt from sudo journalctl -u python3-validity -b again:
May 25 10:20:44 maarten-zbook-g5 systemd[1]: python3-validity.service: Scheduled restart job, restart counter is at 4.
May 25 10:20:44 maarten-zbook-g5 systemd[1]: Started python-validity driver dbus service.
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:>cmd> 3e
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:<cmd< 0000ef004000001001000001010005000104070000100000001000000201020000200000005005000606030000700500008000000302170000f0050000f004000403050000e00a0000200500
May 25 10:20:45 maarten-zbook-g5 python3[239261]: INFO:root:Flash has 5 partitions.
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:>cmd> 01
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:<cmd< 0000f0b05e54a4000000060701300001000045a64a706abf0023000000000100000003d10007
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:>cmd> 19
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:<cmd< 0000000301020001000000000000000000000000d8fc6e5c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:>cmd> 4302
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:<cmd< 0000010002000800a558265e0100344602000700d03c00000100840801000700800600000200842803001200701000000200763601000c00000a00000100864700000100505a00000200237700000100c02f00000200003700000100b0080200010025560000010060040000
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:>cmd> 06020000014a231406e5542fc6dc3b1aedebe68f55596ad3ca13f6e019994c6f71672fff756fbde0511d09d45978b12ba415b3694a0e76348c8cfe9dbb9abf86813fc0c67c1005519a6f87360c2fb3e12bd0a9e012b06d9f5c9b44ccc6645b0fbd47afe45c8c874fcb88fbfd18fb7a9b3241351f256acce689f9586a52b01f8fdcb66cdf3b340b1f9f386d58ca24fdfcdfbcebefb5f3a3c2a08357721040235a20ce1ee2f4f7856e0d9c27b92cd9b975c86f>
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:<cmd< 0000
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:>cmd> 40010100000000000000100000
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:<cmd< 0000001000000000000001006e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d000400a10037fd204a4991b240b272611c2f0f2aab72da709dd5e57d4dcab4d267bd72fede025e4faa932fac83966840cd24f623e0518cf16eaa9feaa16c929daca3a088fb9a497337434b23751f4a270df60de62c36e22a7bf7a9fd5dbc4da179858a6c1176c38c64705ec45bd31f070798fdafe6c72d119c018c65b7f575e4f63b67bc934d>
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:block id 0000 (1 bytes)
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:block id 0004 (161 bytes)
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:Private key:
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:x=0x32c050a000d9989775f0afe7657ff2f764c500d34042db660f5272f81dcbf1d6
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:y=0x69e6577e7035e0d4d7d70fbe723cb71b8dd3151710e298595fc27ad74bee4751
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:d=0x80c11ea182beb8b539eb9a15eee134fc64e6d915b34fa6d3748e0c50085f820
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:block id 0003 (184 bytes)
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:TLS cert blob: b'1700000020000000d6f1cb1df872520f66db4240d300c564f7f27f65e7aff0759798d900a050c0320000000000000000000000000000000000000000000000000000000000000000000000005147ee4bd77ac25f5998e2101715d38d1bb73c72be0fd7d7d4e035707e57e6690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f37003cf483a409947b6b5466a106efb2466764d6>
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:block id 0005 (420 bytes)
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:unhandled block id 0005 (420 bytes): b'170000000001000001000000fcffffffffffffffffffffff00000000000000000000000001000000ffffffff0000000000000000000000000000000000000000000000000000000000000000000000004b60d2273e3cce3bf6b053ccb0061d65bc86987655bdebb3e7933aaad835c65a00000000000000000000000000000000000000000000000000000000000000000000000096c298d84539a1f4a033eb2d817>
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:block id 0001 (256 bytes)
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:block id 0002 (256 bytes)
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:block id 0006 (400 bytes)
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:ECDH params:
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:x=0xe150956fee2ffdfcf381ce2e271090d195de484da702e167d9161595513dd67
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:y=0x730476c78477e9daf76a557ddce958002ee4c538e1283b8227d84064844c4c3e
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:>cmd> 440000001603030045010000410303841b81c402a302c295f59d3d84f10843b420e5f12883303b6963e0a67ec1de6107000000000000000006c005003d008d00000a000400020017000b00020100
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:<cmd< 160303003d0200002d030300012f7630226d678fed5aeafe5cd952ebee6e25f2648a7a452077aab2d05c4507544c5330226d67c005000d000004014000000e000000
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:>tls> 16: 1400000cfbbd5ffb5b08790422090de3
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:>cmd> 4400000016030301540b0000c00000b80000b8ac161700000020000000d6f1cb1df872520f66db4240d300c564f7f27f65e7aff0759798d900a050c0320000000000000000000000000000000000000000000000000000000000000000000000005147ee4bd77ac25f5998e2101715d38d1bb73c72be0fd7d7d4e035707e57e6690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f37003cf48>
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:<cmd< 140303000101160303005016094c8318c6d30dbb8bbde65cb3bb206bf878413df90db0acc01cd6195a5694cba813ddfad17d425e3f2abbcda3c939763275fee1dcbc3e1e3e5ce16af4687f395236a9ce2c604784b2a1f81a46d0f3
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:<tls< 16: 1400000cd516a345b5547d185ba7d280
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:>tls> 17: 4302
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:>cmd> 1703030040911b65f37082fc767da00529a066d2d3b2f3b1bead1f86622e868a8f8a24bab2a453ea960acb7eca0107edb6a2ce70dfdc29ad0d2f8267b502d5a698efc0dbf3
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:<cmd< 17030300a0196eb567d8a9ab185fcc2d8e1c4dc348ca583dc7e1b081cfdfd097dbfc72a5aec5b0967e532bfb03f296c974832728967dfa20d0c606b39f5b0d6fa7252ed37589e0b5f947b9b552a6164efe731534c2cf5a11fc152428acca99e5c617aa49d8b7838e9765b0a03bb7ed9d90bd43bd7b6bf3ee7b1a34bc506dbfef138bedca28c7ddf0c98d2deea84ba517e50eba6d7caa834d26df6a2418749fa734649b6ff7
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:<tls< 17: 0000010002000800a558265e0100344602000700d03c00000100840801000700800600000200842803001200701000000200763601000c00000a00000100864700000100505a00000200237700000100c02f00000200003700000100b0080200010025560000010060040000
May 25 10:20:45 maarten-zbook-g5 python3[239261]: INFO:root:Detected firmware version 1.2 (Tue Jan 21 02:49:25 2020))
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:>tls> 17: 75
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:>cmd> 1703030040e1063cff21a4963fea16ef7142a142a7ee9b7d0b166829fea36b40ee0a9ddd899704bf973382f53b284f084f73829764d2c8d22b8ce5340d7e205c079aee13d4
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:<cmd< 1703030040addc1ff2fb6d995b3276cb508ddf0d44b1c490f0a8248f42188aa03960a31921e78a079fbfc42dbdb3693ea2643cdec350aea1319c8ee0d52be0c9446ce1d248
May 25 10:20:45 maarten-zbook-g5 python3[239261]: DEBUG:root:<tls< 17: 00000000000071009001
May 25 10:20:45 maarten-zbook-g5 python3[239261]: INFO:root:Opening sensor: 57K0 FM- 154-123
May 25 10:20:45 maarten-zbook-g5 dbus-service[239261]: Traceback (most recent call last):
May 25 10:20:45 maarten-zbook-g5 dbus-service[239261]:   File "/usr/lib/python-validity/dbus-service", line 324, in <module>
May 25 10:20:45 maarten-zbook-g5 dbus-service[239261]:     main()
May 25 10:20:45 maarten-zbook-g5 dbus-service[239261]:     ~~~~^^
May 25 10:20:45 maarten-zbook-g5 dbus-service[239261]:   File "/usr/lib/python-validity/dbus-service", line 281, in main
May 25 10:20:45 maarten-zbook-g5 dbus-service[239261]:     init.open()
May 25 10:20:45 maarten-zbook-g5 dbus-service[239261]:     ~~~~~~~~~^^
May 25 10:20:45 maarten-zbook-g5 dbus-service[239261]:   File "/usr/lib/python3.14/site-packages/validitysensor/init.py", line 50, in open
May 25 10:20:45 maarten-zbook-g5 dbus-service[239261]:     open_common()
May 25 10:20:45 maarten-zbook-g5 dbus-service[239261]:     ~~~~~~~~~~~^^
May 25 10:20:45 maarten-zbook-g5 dbus-service[239261]:   File "/usr/lib/python3.14/site-packages/validitysensor/init.py", line 36, in open_common
May 25 10:20:45 maarten-zbook-g5 dbus-service[239261]:     sensor.open()
May 25 10:20:45 maarten-zbook-g5 dbus-service[239261]:     ~~~~~~~~~~~^^
May 25 10:20:45 maarten-zbook-g5 dbus-service[239261]:   File "/usr/lib/python3.14/site-packages/validitysensor/sensor.py", line 252, in open
May 25 10:20:45 maarten-zbook-g5 dbus-service[239261]:     raise Exception('Device %s is not supported (sensor type 0x%x)' %
May 25 10:20:45 maarten-zbook-g5 dbus-service[239261]:                     (self.device_info.name, self.device_info.type))
May 25 10:20:45 maarten-zbook-g5 dbus-service[239261]: Exception: Device 57K0 FM- 154-123    is not supported (sensor type 0x969)
May 25 10:20:45 maarten-zbook-g5 systemd[1]: python3-validity.service: Main process exited, code=exited, status=1/FAILURE
May 25 10:20:45 maarten-zbook-g5 systemd[1]: python3-validity.service: Failed with result 'exit-code'.
May 25 10:20:46 maarten-zbook-g5 systemd[1]: python3-validity.service: Scheduled restart job, restart counter is at 5.
May 25 10:20:46 maarten-zbook-g5 systemd[1]: python3-validity.service: Start request repeated too quickly.
May 25 10:20:46 maarten-zbook-g5 systemd[1]: python3-validity.service: Failed with result 'start-limit-hit'.
May 25 10:20:46 maarten-zbook-g5 systemd[1]: Failed to start python-validity driver dbus service.

There's a lot of debug output that I don't understand, but the most important line appears to be near the end:

Exception: Device 57K0 FM- 154-123 is not supported (sensor type 0x969)

@DataConnection
Copy link
Copy Markdown

I was getting a similar error - it seems that the sensor is not 0xd51 but 0x969 for the HP ZBook G6. I changed (without actually knowing what I'm doing) the lines 238 in sensors.py to

        if self.device_info.type == **0x969:**
            logging.info('Sensor type 0x969 — aliasing to 0x199 profile')
            self.device_info.type = 0x199
    

Afterwards I could start the python3-validity service and enroll my fingerprint. But fprintd-verify won't work.
Maybe the solution lies in the hardware.py - my device 06cb:00b7 is referred as 57K0 FM-3439-002:

DeviceInfo(0x0190, 0x0969, 0x85, 0xff, '57K0 FM-3439-002   '),

There is also a line for mpsijm's device, referring to the same sensor type:
DeviceInfo(0x0190, 0x0969, 0x71, 0xff, '57K0 FM- 154-123 '),

@mpsijm : thanks for the adapted makepkg file - I'm also using Arch.

@mpsijm
Copy link
Copy Markdown

mpsijm commented May 27, 2026

Nice progress! 😄 After making the same change in sensor.py:238, I can confirm the same symptoms:

$ fprintd-enroll 
Using device /net/reactivated/Fprint/Device/0
Enrolling right-index-finger finger.
Enroll result: enroll-stage-passed
Enroll result: enroll-retry-scan
Enroll result: enroll-stage-passed
Enroll result: enroll-stage-passed
Enroll result: enroll-retry-scan
Enroll result: enroll-stage-passed
Enroll result: enroll-stage-passed
Enroll result: enroll-stage-passed
Enroll result: enroll-completed

For the output above, I put my finger on the scanner between each line.

$ fprintd-verify 
Using device /net/reactivated/Fprint/Device/0
Listing enrolled fingers:
 - #0: right-index-finger

No matter how often I put my finger on the scanner, nothing happens, until I hit Ctrl+C to terminate the command.

Also, here's the log for sudo journalctl -u python3-validity -b when I run fprintd-verify (the only logs are from starting the command and interrupting it, nothing in between):

(lines truncated due to lengthy hex strings and no clue if I'd be leaking cryptographic secrets)

May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:In ListEnrolledFingers maarten
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:>tls> 17: 4b00000b0053746757696e64736f7200
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:>cmd> 1703030050965b4c906b71a0be1a3603[...total 170 hex digits...]
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:<cmd< 1703030050c2b3a8f7f1781a1d3658a1[...total 170 hex digits...]
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:<tls< 17: 0000030002000b00000005004c000d004c0053746757696e64736f7200
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:>tls> 17: 4a000003004c00030000001c00000001[...total 166 hex digits...]
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:>cmd> 17030300903b6c04228ef9ee7d61d893[...total 298 hex digits...]
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:<cmd< 170303009068733d24e10137c0719cc0[...total 298 hex digits...]
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:<tls< 17: 00000d00010000004c000e0002000300[...total 188 hex digits...]
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:['right-index-finger']
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:In VerifyStart for maarten, right-index-finger
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:>tls> 17: 4b00000b0053746757696e64736f7200
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:>cmd> 1703030050d0dc510e6f7b8fadb27988[...total 170 hex digits...]
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:<cmd< 1703030050d3891ae29b0db5b407b1b8[...total 170 hex digits...]
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:<tls< 17: 0000030002000b00000005004c000d004c0053746757696e64736f7200
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:>tls> 17: 4a000003004c00030000001c00000001[...total 166 hex digits...]
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:>cmd> 1703030090658f595efe4ec53c2279c9[...total 298 hex digits...]
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:<cmd< 1703030090966f209226e8a4dad32d19[...total 298 hex digits...]
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:<tls< 17: 00000d00010000004c000e0002000300[...total 188 hex digits...]
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:VerifyFingerSelected
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:>tls> 17: 3920bf0200ffff000001990020000000[...total 250 hex digits...]
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:>cmd> 17030300b02336dbe9291e541063585b[...total 362 hex digits...]
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:<cmd< 170303004059fe0bf0cb7478403e3b9d[...total 138 hex digits...]
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:<tls< 17: 0000
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:>tls> 17: 02780000002300000020000800002000[...total 27482 hex digits...]
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:>cmd> 17030335e027c198d2df9faf50dd944f[...total 27594 hex digits...]
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:<cmd< 17030307e06c82354482100856e36ec8[...total 4042 hex digits...]
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:<tls< 17: 0000880200305e000000eaf7f9fcfefe[...total 3932 hex digits...]
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:<int< 0000000000
May 27 22:26:14 maarten-zbook-g5 python3[27645]: DEBUG:root:<int< 0320070000
May 27 22:27:40 maarten-zbook-g5 python3[27645]: DEBUG:root:>tls> 17: 04
May 27 22:27:40 maarten-zbook-g5 python3[27645]: DEBUG:root:>cmd> 1703030040ef8bac142fd7df8cbf2411[...total 138 hex digits...]
May 27 22:27:40 maarten-zbook-g5 python3[27645]: DEBUG:root:<cmd< 1703030040ee977ce4d6d984e3588608[...total 138 hex digits...]
May 27 22:27:40 maarten-zbook-g5 python3[27645]: DEBUG:root:<tls< 17: 1204
May 27 22:27:40 maarten-zbook-g5 python3[27645]: DEBUG:root:>tls> 17: 39f4010000f401000001ff0020000000[...total 250 hex digits...]
May 27 22:27:40 maarten-zbook-g5 python3[27645]: DEBUG:root:>cmd> 17030300b08a3239c81a97fb1d046061[...total 362 hex digits...]
May 27 22:27:40 maarten-zbook-g5 python3[27645]: DEBUG:root:<cmd< 17030300405da64d716bfc75fc92d084[...total 138 hex digits...]
May 27 22:27:40 maarten-zbook-g5 python3[27645]: DEBUG:root:<tls< 17: 0000
May 27 22:27:40 maarten-zbook-g5 ERROR:root[27645]: Traceback (most recent call last):
                                                      File "/usr/lib/python3.14/site-packages/validitysensor/usb.py", line 161, in wait_int
                                                        resp = self.dev.read(131, 1024, timeout=100)
                                                      File "/usr/lib/python3.14/site-packages/usb/core.py", line 1043, in read
                                                        ret = fn(
                                                                self._ctx.handle,
                                                        ...<2 lines>...
                                                                buff,
                                                                self.__get_timeout(timeout))
                                                      File "/usr/lib/python3.14/site-packages/usb/backend/libusb1.py", line 868, in intr_read
                                                        return self.__read(self.lib.libusb_interrupt_transfer,
                                                               ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                                                           dev_handle,
                                                                           ^^^^^^^^^^^
                                                        ...<2 lines>...
                                                                           buff,
                                                                           ^^^^^
                                                                           timeout)
                                                                           ^^^^^^^^
                                                      File "/usr/lib/python3.14/site-packages/usb/backend/libusb1.py", line 958, in __read
                                                        _check(retval)
                                                        ~~~~~~^^^^^^^^
                                                      File "/usr/lib/python3.14/site-packages/usb/backend/libusb1.py", line 602, in _check
                                                        raise USBTimeoutError(_strerror(ret), ret, _libusb_errno[ret])
                                                    usb.core.USBTimeoutError: [Errno 110] Operation timed out
                                                    
                                                    During handling of the above exception, another exception occurred:
                                                    
                                                    Traceback (most recent call last):
                                                      File "/usr/lib/python-validity/dbus-service", line 142, in run
                                                        usrid, subtype, hsh = sensor.identify(update_cb)
                                                                              ~~~~~~~~~~~~~~~^^^^^^^^^^^
                                                      File "/usr/lib/python3.14/site-packages/validitysensor/sensor.py", line 953, in identify
                                                        raise e
                                                      File "/usr/lib/python3.14/site-packages/validitysensor/sensor.py", line 947, in identify
                                                        self.capture(CaptureMode.IDENTIFY)
                                                        ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
                                                      File "/usr/lib/python3.14/site-packages/validitysensor/sensor.py", line 739, in capture
                                                        b = usb.wait_int()
                                                      File "/usr/lib/python3.14/site-packages/validitysensor/usb.py", line 168, in wait_int
                                                        raise CancelledException()
                                                    validitysensor.usb.CancelledException
May 27 22:27:40 maarten-zbook-g5 python3[27645]: DEBUG:root:VerifyStatus

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Can You add Support to 138a:00ab Validity Sensors, Inc. Support for Synaptics 06cb:00b7 (Sensor Type 0xd51) Support for 138a:00ab?

3 participants