Expand description
Platform-agnostic core of ssh-stamp.
Hosts the SSH state machine, configuration handling, and the
platform::PlatformServices / serial::BufferedSerial traits that a
per-MCU adapter crate (e.g. ssh-stamp-esp32) implements.
§Architecture
ssh-stamp is firmware that turns a microcontroller into an SSH-accessible
serial bridge. Connect via SSH to the device, and your terminal session is
bridged directly to the device’s UART.
The design separates platform-agnostic logic (this crate) from
platform-specific implementations (port crates like ssh-stamp-esp32).
All hardware access flows through traits defined in ssh_stamp_hal or
through platform::PlatformServices.
§Crate structure
ssh_stamp_hal— hardware abstraction traits (WifiHal,NetworkProviderHal,OtaActions, etc.)ssh_stamp_esp32— ESP32 port: trait implementations, bootable binary, per-target UART pin assignmentsssh_stamp_esp32_boards— per-board pin mappings and the board catalogssh_stamp_ota— SFTP-based OTA update server (TLV header parsing, chunked flash writes, device reset; includes thepackerhost utility)
ssh-stamp-ota depends on ssh-stamp-hal for OtaActions
and is in turn depended on by ssh-stamp for SFTP-based updates.
§Repository layout
Platform-agnostic crates live at the repository root. Everything
specific to one chip manufacturer lives under
boards/ssh-stamp-<manufacturer>/, one directory per manufacturer:
ssh-stamp/
├── src/ ssh-stamp (this crate)
├── ssh-stamp-hal/ hardware abstraction traits
├── ssh-stamp-ota/ SFTP OTA server and `packer` tool
├── xtask/ build, flash and test runner
└── boards/
└── ssh-stamp-esp/ Espressif
├── ssh-stamp-esp32/ port crate: HAL impls and firmware binary
├── ssh-stamp-esp32-boards/ board support: `boards/*.toml` pin maps
└── ssh-stamp-esp32-hil/ hardware-in-the-loop testsA new manufacturer gets its own boards/ssh-stamp-<manufacturer>/
directory with the same three crates; see “Adding a new port” in
ssh_stamp_hal.
§Key modules
app— entry pointsprepare_ap_configandrun_apphandle— SSH event handlers (auth, channels, env vars)serve— SSH connection loopserial— UART bridge trait and bridge functionconfig—SSHStampConfigstruct and serializationstore— Flash load/save/createplatform—PlatformServicestrait (save config, reset, OTA)
§Hacking
§Architectural invariants
src/is platform-agnostic. It must not importesp-hal,esp-radio,esp-storage, or any platform-specific crate. All hardware access goes throughssh-stamp-haltraits orPlatformServices.- Peripherals are owned by the state machine, not globals. UART is an exclusive resource consumed by the serial bridge once SSH attaches.
- Dependency graph is acyclic:
ssh-stamp-hal <- ssh-stamp <- ssh-stamp-<port>.ssh-stampmust not depend on any port crate.
§Adding a new SSH env var handler
Edit handle::session_env. Add a new match arm for the variable name.
Follow the existing pattern: acquire the config lock, apply the change,
set ctx.config_changed = true, and call a.succeed().
§Configuration
On first boot (first_login = true), the device generates a random SSID
and WPA2 PSK (printed to the serial console) and accepts any SSH
connection. The client provisions a public key via the SSH_STAMP_PUBKEY
environment variable. Subsequent connections require that key.
WiFi SSID and PSK can be changed at any time via the SSH_STAMP_WIFI_SSID
and SSH_STAMP_WIFI_PSK env vars. Changes are persisted to flash and the
device performs a software reset.
The serial bridge line settings follow the same route through the
SSH_STAMP_UART_BAUD, SSH_STAMP_UART_DATA_BITS, SSH_STAMP_UART_PARITY
and SSH_STAMP_UART_STOP_BITS env vars, defaulting to 115200 8N1.
§Testing
Host-side OTA TLV tests:
cargo +stable test --package ssh-stamp-ota --target x86_64-unknown-linux-gnuManual testing requires a hardware target, a WiFi client, an SSH client,
and a serial device connected to the UART pins for bridge testing.
§Build-time configuration
The heap and buffer sizes below are declared in build.rs via esp-config
and overridable at build time with the matching environment variable. Note that
these are build time config variables, they are not used at runtime.
| Option | Stability | Default value | Allowed values |
|---|---|---|---|
SSH_STAMP_CONFIG_HEAP_SIZE Global allocator heap size in bytes | ⚠️ Unstable | 61440 | Integer in range 16384..263168 |
Modules§
- app
- Platform-agnostic application entry points.
- can
- CAN frame encoding/decoding for SSH tunnelling.
- config
- Configuration types and serialization.
- errors
- Application-level error types.
- handle
- SSH event handlers: authentication, channels, environment variables.
- mem_
probe - The benchmarking instrumentation, including checkpoints and replay. Timing is not related to the platform in any way, so it doesn’t need to live inside the binrary crate.
- platform
- Platform services abstraction.
- serial
- serve
- SSH connection loop orchestration.
- settings
- Compile-time constants: default IP,
WiFicharacter set, buffer sizes. - store
Macros§
- bench_
emit - Emits a structured benchmark line.