Hardware abstraction / 2024 to present
Lemnos
Lemnos addresses a common embedded failure mode: application logic becomes coupled to whichever Linux path and vendor driver exposed a device during development.
Explore repositoryLinux paths describe where a device appeared, not its stable identity or capabilities.
When applications also choose drivers and handle hotplug themselves, platform assumptions leak through every consumer and tests rarely exercise the real binding lifecycle.
I split discovery, compatibility, binding, and bus access into separate contracts.
Inventory diffs identify what changed, manifests preserve why a driver matched, typed sessions isolate the backend, and incremental refresh revisits only affected bindings.
Hardware identity survives changing device paths.
Discovery produces an inventory, manifests explain compatibility, and the registry selects a driver before bus sessions are opened. Hotplug becomes a visible state transition instead of an application-side path failure.
Linux probes or mock backend
Descriptors · snapshots · diffs · watch events
Compatibility rules · ranked candidates
Chosen driver · resources · lifecycle
GPIO · PWM · I²C · SPI · UART · USB
Bound, typed driver state
- Linux transports
- Mock hardware
- Driver conformance harness
The decisions beneath the summary.
Identity before location
Linux, configured, and mock probes produce device descriptors and inventory snapshots. The discovery layer diffs those snapshots and emits focused events, while applications consume identity and capabilities rather than /dev paths. A failed partial probe can preserve known inventory instead of making every previously bound device disappear.
- Inventory diffs separate additions, removals, and changes so consumers can react only to affected devices
- A failed partial probe retains known devices and reports an issue instead of clearing the complete inventory
- Linux path and transport details remain behind the backend while the shared API exposes identity and capabilities
Explainable driver selection
Driver manifests declare identity, supported interactions, and compatibility. The registry scores candidates and preserves a match report; only then does the runtime create a bind context and open the typed sessions the selected driver needs. An operator or test can explain why one driver won rather than reverse-engineering a chain of conditionals.
- The match report retains each candidate and its compatibility evidence for inspection
- The selected driver receives a typed bind context rather than raw backend internals
- Driver conformance helpers exercise matching, binding, interaction, and failure behavior against the same contracts
Typed bus and test boundary
GPIO, PWM, I²C, SPI, UART, and USB are typed session contracts. Linux backends implement physical access; the mock backend scripts devices and failures through the same discovery, bind, interaction, and removal lifecycle. Drivers do not need test-only branches or awareness of which backend supplied the bus.
- lemnos-bus defines narrow backend-facing session contracts
- lemnos-mock supports examples, application tests, driver tests, and scripted failure cases
- Compile-time macro tests remain separate from runtime and backend conformance coverage
Incremental refresh and rebind
Watch events can refresh affected inventory slices, compare metadata and identity, and preserve a binding when only irrelevant metadata changed. Removal transitions the runtime state explicitly; reattachment can run matching again and restore the driver automatically. That makes hotplug an ordinary lifecycle rather than an application restart strategy.
- Inventory diffs separate additions, removals, and changes
- Metadata-only changes can avoid unnecessary driver teardown and rebind
- USB removal and reattach paths exercise automatic binding restoration
What this work does not claim.
Lemnos is experimental and not a hidden HeliOS product dependency.
A high-scoring compatibility match still requires real-device conformance for hardware-specific behavior.
Hotplug and bus semantics differ by platform, so the shared model deliberately does not erase every backend distinction.
Architecture, evidence, and limits.
Explore repository ↗Architecture
- 01 Identity separated from location
inventory snapshots describe devices and changes without making Linux paths the application API
- 02 Explainable driver selection
declarative compatibility rules are ranked and retained before executable driver behavior is bound
- 03 Typed sessions below drivers
GPIO, PWM, I²C, SPI, UART, and USB drivers do not need to know which backend supplied access
- 04 Mock hardware on the real contracts
tests exercise discovery, matching, binding, interaction, failure, and removal without test-only driver branches
Validation
- 01
Facade examples exercise synchronous and asynchronous mock GPIO plus Linux device validation through the public API
- 02
Mock USB and sensor examples cover discovery, driver matching, interaction, removal, and reattachment as one flow
- 03
Feature-matrix, macro, workspace, and container checks guard optional dependencies and the facade used by applications
Why it matters in practice.
- 01Hardware can move between Linux paths without turning physical location into application configuration
- 02Driver selection produces ranked match evidence instead of hiding compatibility in conditional code
- 03Mock and Linux backends exercise the same discovery, binding, interaction, and removal contracts
- 04Partial probe failures preserve known inventory instead of making healthy bindings disappear
- Discovery model
- Driver matching
- Bus abstractions
- Linux backends
- Rust
- Linux
- GPIO
- I2C / SPI / UART
- Drivers