Ashlar
A display connection stack in Rust — HDMI 2.1 first.
Ashlar takes a display link from raw capability bytes to a trained link: parse what the sink can do, negotiate the best mode the source, sink and cable can all carry, describe it in InfoFrames, and bring up the link over SCDC with FRL training. Each layer is its own crate — use one, or use them all.
An ashlar is a stone dressed to fit its neighbours exactly. The crates are built the same way: each one is small, does one job completely, and meets the next layer at a typed, documented boundary.
- The stack — the layers and what each one is responsible for
- Crates — every crate, its layer and its status
- Getting started — which crates to add for what you are building
- Principles — the design rules every crate follows
All crates are open source under the MPL-2.0 and published on crates.io.
The stack
Integration layer compositor glue · DRM/KMS · source capability query (planned)
Driver-adjacent layer FRL link training plumbob · plumbob-async
Protocol layer CEC · eARC (planned)
Signaling layer InfoFrames · SCDC cartouche · culvert · culvert-async
Negotiation layer enumeration · validation · ranking concordance
Parsing layer EDID · DisplayID piaf
Shared types display vocabulary display-types
Hardware abstraction SCDC transport · PHY hdmi-hal · hdmi-hal-async · hdmi-hal-i2c-dev
From bytes to a trained link
The critical path — what a minimal working HDMI 2.1 link needs, in order:
| Step | What happens | Crate | Status |
|---|---|---|---|
| 1 | Parse the sink’s EDID / DisplayID into typed capabilities | piaf | Released |
| 2 | Negotiate a ranked list of configurations the sink, source and cable can all carry | concordance | Released |
| 3 | Read and write the sink’s SCDC registers | culvert | Released |
| 4 | Train the FRL link, stepping down rates when the sink asks, falling back to TMDS | plumbob | Released |
| 5 | Run the above against real hardware from Linux userspace | hdmi-hal-i2c-dev | Released |
| 6 | Describe the chosen configuration in InfoFrames | cartouche | Released |
| 7 | Discover the source’s capabilities from DRM/KMS | — | Planned |
| 8 | Turn the negotiated configuration into a DRM atomic modeset | — | Planned |
CEC, eARC and further PHY configuration are off the critical path.
Where policy lives
The parsing and protocol layers are judgment-free: they implement the specification and
report what they find. The negotiation layer is where opinions live — it ranks candidates
by a NegotiationPolicy you can override, and every accepted or rejected candidate carries
a reasoning trace explaining why.
Crates
| Crate | Layer | What it does | Docs |
|---|---|---|---|
| display-types | Shared types | Display capability vocabulary shared across the stack | docs.rs |
| piaf | Parsing | EDID and DisplayID parser | docs.rs |
| concordance | Negotiation | HDMI 2.1 mode negotiation with a full reasoning trace | docs.rs |
| cartouche | Signaling | InfoFrame encoding and decoding (AVI, Audio, HDR Static, HDMI Forum VSI, Dynamic HDR) | docs.rs |
| culvert | Signaling | Typed SCDC register access | docs.rs |
| culvert-async | Signaling | Async companion to culvert | docs.rs |
| plumbob | Driver-adjacent | FRL link training state machine | docs.rs |
| plumbob-async | Driver-adjacent | Async companion to plumbob | docs.rs |
| hdmi-hal | Hardware abstraction | ScdcTransport and HdmiPhy traits | docs.rs |
| hdmi-hal-async | Hardware abstraction | Async companion to hdmi-hal | docs.rs |
| hdmi-hal-i2c-dev | Hardware abstraction | Linux userspace backend over /dev/i2c-N, for development and validation | docs.rs |
| ashlar | — | Facade: one feature per crate above, re-exported under its own name | docs.rs |
Current versions are on crates.io; each crate’s
CHANGELOG.md records what changed in each release.
Getting started
Pick the layers you need. Each crate’s README has a worked example; this page tells you which crates to start from.
| You are building… | Start with |
|---|---|
| A tool that reads and explains a display’s EDID | piaf |
| Mode selection: “what can I drive on this display?” | piaf + concordance |
| InfoFrame generation or inspection | cartouche |
| HDMI 2.1 link bring-up on your own hardware | hdmi-hal + culvert + plumbob |
| The same, on an async executor | the -async companions of the three above |
| Experiments against a real sink from Linux userspace | hdmi-hal-i2c-dev under culvert and plumbob |
Add crates individually:
cargo add piaf concordance
or through the facade, one feature per crate:
cargo add ashlar --features piaf,concordance
For no_std targets, disable default features; each crate’s README lists what remains
available with alloc and without it.
An end-to-end walkthrough — EDID bytes in, a ranked configuration, its InfoFrames and a link-training plan out — is on its way.
Principles
- Hardware behind traits. SCDC transport and PHY control are injected, so all protocol logic is testable without hardware.
- Diagnostics are first-class. Structured reasoning traces and typed warnings instead of logs. Rejected candidates are explained; nothing fails silently.
- Spec-complete, judgment-free lower layers. Parsing and protocol crates implement the spec in full; policy lives in the negotiation layer, and you can override it.
no_stdwhere it matters, async companions where they help.- No unsafe code.
#![forbid(unsafe_code)]across the stack. - Stable output types. Consumer-facing structs are
#[non_exhaustive], so new fields do not break you. - Verifiable releases. Trusted publishing, with SLSA provenance you can check with
gh attestation verify.
Beyond HDMI
Much of Ashlar is not HDMI-specific:
- EDID and DisplayID describe displays on every link — DisplayPort, eDP panels, DVI,
USB-C DisplayPort Alt Mode and USB display adapters.
piafanddisplay-typesserve all of them. - CTA-861 InfoFrame payloads — AVI, HDR Static and Dynamic HDR — are carried by
DisplayPort too, inside its secondary data packets.
cartoucheencodes the payloads. - Negotiation — enumerate, check constraints, rank — has the same shape for any link;
concordance’s built-in constraints are HDMI’s today.
The transport crates (hdmi-hal, culvert, plumbob) are HDMI-only by nature: SCDC and FRL
exist only in HDMI. DisplayPort’s counterparts — the AUX channel, DPCD registers and its own
link training — would be sister crates built the same way. DisplayPort support is a
direction the stack is designed to grow into.