Repository navigation
Description
Environment
- Hardware: Lenovo ThinkPad X1 Yoga Gen 3
- Sensor:
06cb:009aSynaptics, Inc. Metallica MIS Touch Fingerprint Reader - Distro: Ubuntu 24.04, kernel 6.14.0-36-generic
python3-validity 0.15~ppa2,open-fprintd 0.7~ppa2(from PPA)
Summary
After deep (S3) suspend, Resume() frequently fails with
usb.core.USBError: [Errno 19] No such device — roughly half the
time on this machine, depending on how long the sensor was suspended
for. When the kernel re-enumerates the sensor as a new USB device
number, the service still holds the file descriptor from the
pre-suspend device; neither the primary open_common() call nor
the existing except-clause retry reopens the USB device.
When this happens, recovery requires systemctl restart python3-validity
(~1 second), which is long enough for GDM/gnome-shell to poll fprintd,
get an error, and fall back to password prompt — so the sensor never
lights up on lid-open. The rest of the time (short suspends where
USB is not re-enumerated) Resume() works fine.
The current Resume() already tries twice
def Resume(self):
logging.debug('In Resume')
tls.reset()
try:
init.open_common()
except:
init.open_common() # same stale usb.dev — retry is a no-opBoth invocations issue commands through the same usb.dev object.
open_common() runs init_flash() → usb.send_init() → writes over
self.dev — and there is no path in the resume flow that calls
usb.open() again. usb.open() is only invoked at process startup
via init.open().
Timeline of a failed resume (representative)
11:06:08 kernel: PM: suspend exit
11:06:08 open-fprintd: (from resume.py) Manager.Resume
11:06:08 python3-validity: In Resume <- old fd
11:06:09 gdm-fingerprint: gkr-pam: no password is available for user
(GDM has already polled fprintd, got an error, gave up)
11:06:09 dbus-service: USBError [Errno 19] x2 (initial + internal retry)
11:06:09 systemd: Stopped / Started python3-validity (external restart)
11:06:10 python3-validity: Manager is back online, registering
(too late — GDM has moved on)
Suggested fix
Reopen the USB device in the except-clause of Resume():
def Resume(self):
logging.debug('In Resume')
tls.reset()
try:
init.open_common()
except Exception:
# USB device likely re-enumerated across S3; fd is stale.
from validitysensor.usb import usb
usb.close()
usb.open()
init.open_common()This eliminates the need for the external process restart and closes
the race window with the desktop's fingerprint poll.
s2idle resume is unaffected because the USB device is not
re-enumerated — the sensor keeps the same device number, and the
existing retry succeeds. It's specifically the S3 case that breaks.
Related open-fprintd change
Locally I patched open-fprintd's resume.py to (a) cancel any
pending VerifyStop/Release before calling Resume(), and
(b) fall back to systemctl restart python3-validity when
Resume() throws. Happy to open a separate PR to
uunicorn/open-fprintd if that would be useful — but the
process-restart workaround only matters until Resume() handles
stale handles itself.
Reproducibility
Intermittent — approximately 50/50 in a recent 10-resume sample on
this hardware. Longer suspends (multiple hours) fail more often;
short suspends often succeed. The failure mode itself is consistent
whenever it triggers: same USBError from the same code path.
Related issues
- Synaptics 06cb:009a on ThinkPad T480 Not Functioning After Waking From Sleep #59,
open-fprintd-resume.servicefails to start after resuming from suspend #106, Reader works initially on reboot, but stops working after suspend/sleep #187 — same USBError, treated as unrelated; all share
this root cause. - Critical bypass of log screen without fingerprint input #232 — a critical lock-screen bypass, likely a downstream symptom
of stale fprintd state surviving suspend.
Activity
peterzgn commentedon Oct 7, 2026
I can reproduce a closely related failure on a ThinkPad T480s with the same 06cb:009a sensor, and I did some controlled testing that may help narrow this down.
Environment:
Cold boot works normally. The sensor is detected and fingerprint verification works.
After S3 resume, the kernel consistently reports:
With only open-fprintd-suspend enabled and no custom restart workaround, open-fprintd remains in:
and fingerprint authentication is unavailable.
I also tested the restart-after-resume workaround similar to #254. Restarting python3-validity/open-fprintd can bring the D-Bus device back, but I found that D-Bus readiness does not necessarily mean that the sensor is actually ready for a biometric operation.
In one controlled test, after the services had restarted and the device had successfully registered with open-fprintd, the first fprintd-verify produced:
The kernel and python-validity logs at exactly that time showed:
python3-validity then went offline.
Immediately afterward the kernel physically re-enumerated the same sensor:
udev/systemd automatically started python3-validity again and the device registered with open-fprintd.
After this real disconnect/re-enumeration, subsequent fprintd-verify sessions completed normally. One was a normal no-match and the next was verify-match, with no additional USB disconnect or Errno 19.
I also tested manually setting the device's sysfs authorized state from 0 -> 1 before starting the services. That did NOT reproduce the recovery produced by the real USB disconnect/re-enumeration. The device remained on the old USB device number, and the first Verify still caused the disconnect/Errno 19/re-enumeration sequence.
I also enabled power/persist=1 for 06cb:009a. The setting survives suspend and appears to reduce some re-enumeration behavior during resume, but it does not eliminate this first-Verify failure.
One additional observation: a D-Bus readiness check based on Manager.GetDevices() can return one device even when the backend is not truly usable. I observed GetDevices() reporting the sensor while python3-validity had already failed during another recovery experiment.
This seems consistent with the stale USB/device-state theory described in this issue. In particular, there appears to be a difference between merely restarting/re-registering the userspace services and obtaining a genuinely fresh USB device after kernel re-enumeration.
I have kept the full journal logs from these tests and can provide the relevant sections if useful. I would also be happy to test a small Resume() patch (for example explicitly closing/reopening the USB device before open_common()) on this T480s rather than changing the entire installation.