fix(nfc): auto-recover a wedged CCID reader via USB power-cycle #85
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/nfc-reader-auto-recovery"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The problem
The Feitian R502-CL (and cheap CCID readers generally) periodically wedge: the reader keeps detecting a card (
status=reading) but every APDU returns "card absent or mute" (SCARD_E_NO_SMARTCARD/ ICC_MUTE). We confirmed on-device that only a USB power-cycle clears it — restartingpcscdor the app does not. Until now this left cash-out/cash-in taps dead until someone physically replugged the reader.The fix — self-healing
Detect the wedge and power-cycle the reader's USB automatically:
nfc-service.ts: count consecutive read failures; after 3 (gated by a 30 s cooldown so a still-wedged reader can't reset-loop) triggernfc-reader-reset.service. A completed read (Bolt Card or not) clears the count, so normal fumbles don't trip it.nfc-pcscthen re-detects the reader on USB hotplug with no app restart.batm3.nix:nfc-reader-reset.service(oneshot, root) re-binds the reader's USB device (a software replug). It's reader-agnostic — matches the USB CCID interface class (0x0B) — so it also covers a future ACR1252U swap with no config change. A polkit rule lets the unprivilegedbitspireapp start just that one unit (mirrors the existing pcscd polkit grant).Validated live on the batm3
reader disconnected→status=ready. ✅bitspire(non-root) successfully startsnfc-reader-reset.service. ✅nfc-service.jscarries the trigger;pnpm typecheck+ 7 nfc tests + prettier all green.Hardware track (separate, recommended)
The durable fix is a better reader — the research points to the ACS ACR1252U (large antenna for behind-panel mounting, firmware-upgradable, PC/SC drop-in) or the reference Identiv uTrust 3700 F / HID Omnikey 5022 CL. This PR makes any reader's wedge a ~2 s self-heal in the meantime, and the reset helper already works with those readers too.
🤖 Generated with Claude Code