A ~1s background watcher on DeviceRepo samples a cheap FIDO HID presence
fingerprint (vid:pid:serial, by enumeration only — it never opens the
device, so it can't contend with an in-flight read or write) and triggers
a refresh whenever the key is plugged, unplugged or swapped. Every screen
then reflects the current device without the manual Refresh button. The
watcher skips a tick while a refresh/write is in flight and stops cleanly
when the repo is dropped.
Several Configuration-screen fields were blank, wrong, or silently
overwrote a working device on save when talking to RS-Key firmware:
- CONFIG_READ over CTAPHID 0x41 answers with a CBOR `{1: blob}` map, but
the client fed the raw CBOR bytes downstream. The PHY read only worked
by accident for records under 24 bytes and broke once a product name
pushed it over; the LED read never worked. Decode the map and return
the inner record.
- Parse the LED status block at the correct stride ((len-1)/4) in one
shared helper, fixing the CCID path that read a 17-byte block as a
legacy 9-byte one (colour shown as the effect id).
- Read hardware LED (GPIO/brightness/driver) and touch-timeout as
optionals: an absent phy tag now means "firmware default" (blank
field) and is not written back, so a virgin phy is no longer clobbered
with GPIO=0 / driver=Pico / brightness=0 on the next Apply. A value is
written only when the user sets one.
- Hide the "Supported Curves" card for RS-Key: its firmware ignores the
phy ENABLED_CURVES tag (curve support is compile-time), so the toggles
were a no-op that also wrote a meaningless tag on save.
- Preserve each status' LED effect/speed on a colour write (read-modify-
write), reject over-long product names, read the enabled USB apps over
the 0xC2 vendor command, and fall back to the USB product string when
the phy record carries no product override.
- Reversed transport priority: PCSC/Rescue preferred over FIDO
- Added `RescueCurves` bitflags re-export to `hal/types.rs`
- Replaced single secp256k1 toggle with full "Supported Curves" card
(11 curves) gated on RS-Key, with mask-building in apply_changes
- Updated FIDO/Rescue write status messages to match transport behavior
- Cleaned up device status display (green "Online" for RS-Key)
Changes: src/ui/screens/config/view.rs, view_model.rs, hal/io.rs, hal/transport/mod.rs, hal/types.rs.
- Add //! module-level headers and /// item-level docs to every source file
- Fix unresolved doc links in hal/mod.rs, ui/mod.rs, transport/pcsc.rs, transport/fido.rs
- Add #![deny(missing_docs)] at crate root to enforce doc completeness in CI
- Move HidTransport from hal/fido/hid.rs to hal/transport/fido.rs
- Add PcscTransport in hal/transport/pcsc.rs for CCID communication
- Refactor DeviceHandle::Rescue to hold PcscTransport instead of bare FirmwareType
- Split monolithic rescue/mod.rs into high-level interface and ops.rs with APDU logic
- Rename hal/fido/hid.rs → hal/fido/ops.rs (FidoOperations), depend on transport::fido
- Update FIDO config-write capability checks with more specific trait methods
- Fix all import paths in hal/io.rs and ui/models/device.rs
This commit significantly refactors the HAL layer to introduce proper support for the RS-Key firmware and abstraction across different hardware profiles
(PicoFido, RSKey, LkOne).
Key changes include:
- **Firmware Abstraction**: Added `FirmwareTrait` and `AnyFirmware` in `src/hal/firmwares/mod.rs` with specific implementations for `PicoFidoFirmware` and
`RSKeyFirmware` to decouple hardware-specific logic from the high-level `io.rs` layer.
- **RS-Key FIDO Support**: Implemented RS-Key payload logic in `src/hal/fido/mod.rs` to support reading/writing LED configuration and DEV_CONF directly over
the CTAPHID FIDO transport using TLV and custom command targets.
- **Constants Cleanup**: Stripped out and consolidated 200+ lines of raw CTAP2 constants and vendor opcodes from `src/hal/fido/constants.rs` to clean up the
module.
- **UI & PIN Dialogs**: Updated `src/ui/screens/config/view_model.rs` to route `DeviceMethod` correctly when applying configurations. Added
`StatusDialogHandle` integration to prompt the user for their FIDO PIN and instruct them to "Please touch your device if it flashes" when performing hardware
config writes over FIDO.
- **LkOne Type**: Added the `LkOne` AAGUID and firmware types to the hardware definition tree.
- **Home View Check**: Fixed a UI issue in `home/view.rs` to conditionally display the LED config card based on whether the `FirmwareType` actually supports
FIDO config modifications (like RS-Key).
This lays the architectural foundation needed to handle FIDO configurations dynamically based on the discovered firmware type.
Break the UI→HAL dependency: Views and ViewModels no longer import
`crate::hal` directly. DeviceRepo is the single bridge — it re-exports
all needed types, provides 16 blocking static methods for background
tasks, and owns all state mutations + event emissions.
- device.rs: Add FreshDeviceState, apply_fresh_state(), update_fido_info(),
read_device_serial_blocking(), 16 *_blocking() wrappers, full re-exports
- app.rs: Remove unconditional passkeys nilling on sidebar navigation;
only invalidate on device_changed (replug). Remove stale
refresh_device_status method.
- config/view_model.rs: Replace all io::* / fido::* calls with
DeviceRepo::*_blocking(). Use apply_fresh_state() instead of refresh()
for RS-Key LED/management writes.
- passkeys/view_model.rs: Replace all io::* calls with
DeviceRepo::*_blocking(). Fix sync_fido_state to use
repo.update_fido_info() instead of manual field mutation.
Restore refresh_if_unlocked via DeviceEvent subscriber.
- Update all view imports: hal::types → ui::models::device,
hal::rescue::constants → ui::models::device
- Update docs in main.rs, app.rs, ui/mod.rs to reflect the new architecture
- Decompose flat about.rs/home.rs/security.rs/config.rs/passkeys.rs into
per-screen directories with mod.rs, view.rs, view_model.rs
- Extract ApplicationRoot, LayoutState, ActiveView, ViewModelStore into new app.rs
- Replace DeviceConnectionState (snapshot-based) with reactive Entity<DeviceRepo>
- Replace ViewCache with ViewModelStore using uniform get_or_insert_with lazy init
- Add AppModels DI bag shared across all view constructors
- Move side types (UsbIdentityPreset, LedDriverType, etc.) into local view_model files
- Delete src/ui/types.rs
- Strip thinking-out-loud and notes-to-self comments from
device/fido/hid.rs, device/rescue/mod.rs, error.rs, ui/views/passkeys.rs
- Replace redundant let c_i = i binding with direct i usage (Copy type)
- Replace magic number 8 with LedColor::all().len() in config.rs
Summary of changes:
- src/device/fido/constants.rs — added ML-DSA-44/65/87 post-quantum COSE algorithm variants (-48 to -50); updated from_raw/Display; refreshed VendorCommand docs with version history and RS-Key caveat; removed stale CTAP2-vs-firmware discrepancy comment
- src/device/rescue/constants.rs — added 8 new curve flags to RescueCurves (SECP256R1, SECP384R1, SECP521R1, BP256R1/384R1/512R1, ED25519, ED448, CURVE25519, CURVE448); corrected MANAGEMENT_AID doc to say it's available on both firmwares
Non-breaking. All additions are purely additive:
- CoseAlgorithm — only accessed via from_raw() (has _ => None catch-all) — existing match arms unaffected
- RescueCurves — bitflags! type, existing code only touches SECP256K1 via contains/bits — new flags don't affect those
- cargo check and cargo clippy both pass clean with no warnings