Add support for sensor type 0xd51 (138a:00ab HP 840 G5, 06cb:00b7 HP G6)#256
Add support for sensor type 0xd51 (138a:00ab HP 840 G5, 06cb:00b7 HP G6)#256SimpleX-T wants to merge 9 commits into
Conversation
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
|
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 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.
|
Hey @DataConnection, sorry, this is on me. When I added 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-verifyIf 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. |
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).
|
Thanks a lot for your effort and the additional commits - now it installs flawlessly (despite showing one error when running But starting python3-validity.service fails: USB devices: Any ideas? I'm stuck. |
|
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-validityLet me know if this works |
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.
|
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 I installed your branch by patching the
|
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.
|
Hi @mpsijm — sorry for the slow reply. That Just pushed cd0def0 to the branch, which fixes it: a defensive USB reset at the start of To update on Arch via your patched AUR PKGBUILD: since you have Re your Let me know how the rebuild goes! |
|
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 Excerpt from
|
|
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 Afterwards I could start the python3-validity service and enroll my fingerprint. But fprintd-verify won't work. There is also a line for mpsijm's device, referring to the same sensor type: @mpsijm : thanks for the adapted makepkg file - I'm also using Arch. |
|
Nice progress! 😄 After making the same change in For the output above, I put my finger on the scanner between each line. 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
|
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
sudofingerprint auth.06cb:00b7is 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 toblobs_97/blobs_9a, spoofing the sensor type to0x199— and consistently hit a wall where the service starts butfprintd-verifyhangs forever orenroll-retry-scanloops 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 tob[0]=3capture events.Sensor.capture()'swhile True: if b[0]==2: breakloop 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
validitysensor/usb.pyDEV_AB = (0x138a, 0x00ab)andDEV_B7 = (0x06cb, 0x00b7)toSupportedDevicesvaliditysensor/blobs.py0x00ab→blobs_97,0x00b7→blobs_9a. Verified accepted by the 0xd51 chip cleartext during initvaliditysensor/firmware_tables.py6_07f_hp_cmit_mis_qm.xpfwext, extracted from HP softpaq sp135736.exe). 0xd51 ships with firmware pre-loaded soupload_fwextreturns early in normal usevaliditysensor/sensor.py0xD51toline_update_type1_devices. (b) InSensor.open(), save the real device type and alias0xd51→0x199before downstream lookups (no nativeSensorTypeInfo/SensorCaptureProgexists for 0xd51). (c) InSensor.capture(), acceptb[0]=3in the wait-for-finger loop only when the real device type is0xd51, and pass the interrupt through to the wait-capture-complete loop so it isn't consumed twicedebian/python3-validity.udev138a:00aband06cb:00b7to the auto-start match blockConstraints and design choices
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.SensorTypeInfoandSensorCaptureProgfor 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.SensorTypeInfofor0x199is reused rather than introducing a new entry. The on-chip image processor uses the chip's own calibration; the wrongbytes_per_lineis masked because matching happens on the chip side.SensorCaptureProg— the spoof lets the existing 0x199 program be reused. Comments in the code make this explicit so the future-correct fix is obvious.dev.reset()defensive patches inusb.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.servicereachesactive (running)(previously failed atinit_flash,sensor.open, orcapture()depending on which patch combo was tried)fprintd-enrollcompletes with realenroll-stage-passedevents (not auto-completed fillers)fprintd-verifyreturnsverify-matchfor the enrolled fingerfprintd-verifyreturnsverify-no-matchfor a different finger (proves the matcher actually distinguishes)sudo -k && sudo whoamiunlocks via fingerprint touch, no passwordcmd6bresponses) 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)