Add host UCSI source and USB-C TUI tab - #162
Conversation
There was a problem hiding this comment.
Pull request overview
Adds host-side UCSI (USB-C) support to ec-test-lib and surfaces it in ec-test-tui via a new USB-C tab and dashboard card, with ACPI (Windows) and deterministic mock backends plus explicit “unsupported” behavior for the serial backend.
Changes:
- Introduces platform-neutral UCSI mailbox decoding +
UcsiSourcetrait inec-test-lib, with Windows ACPI and mock implementations and explicit serial “unsupported” errors. - Adds a
UcsiUpdaterand sharedUcsiStateto poll version/capability/connector state on a fixed interval. - Adds a compact Ratatui USB-C UI module, integrates it as a new tab and dashboard card, and wires it into app navigation/rendering.
Reviewed changes
Copilot reviewed 12 out of 13 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| ec/test-tui/src/updater.rs | Adds UcsiUpdater to poll UCSI cells and publish into shared state. |
| ec/test-tui/src/ucsi.rs | New stateless USB-C/UCSI UI renderer for tab + dashboard card. |
| ec/test-tui/src/state.rs | Adds UcsiState and UCSI_CONNECTOR constant using Fetched<T> cells. |
| ec/test-tui/src/source.rs | Extends DynSource with default UCSI methods + blanket impl via ec_test_lib::UcsiSource. |
| ec/test-tui/src/main.rs | Wires new UCSI state and updater task into the TUI runtime. |
| ec/test-tui/src/app.rs | Adds “USB-C” tab/module and a dashboard card slot; updates tab navigation. |
| ec/test-lib/src/ucsi.rs | New UCSI value types + mailbox validation/decoding helpers with unit tests. |
| ec/test-lib/src/serial.rs | Implements UcsiSource as explicitly unsupported over serial + test for error kind mapping. |
| ec/test-lib/src/mock.rs | Adds deterministic UcsiSource implementation for the mock backend. |
| ec/test-lib/src/lib.rs | Introduces UcsiSource trait; extends Source supertrait and adds Arc<T> blanket impl. |
| ec/test-lib/src/acpi.rs | Adds Windows ACPI \_SB.ECT0.USND UCSI command path + mailbox decoding/error mapping. |
| ec/Cargo.lock | Updates crossbeam-epoch lockfile entry to 0.9.20. |
| common/supply-chain/config.toml | Updates supply-chain exemption for crossbeam-epoch to 0.9.20. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 16 changed files in this pull request and generated no new comments.
Suppressed comments (1)
ec/test-tui/src/updater.rs:416
UcsiUpdater::update()pollsget_ucsi_version()on every tick even though the UCSI version is effectively static. For real backends (e.g. ACPI), this adds an extra mailbox transaction per interval and is redundant after the first successful (or failed) read. Consider only fetching/storing the version whenstate.versionis stillNone(e.g. on startup) and only refreshing the other fields on subsequent ticks.
// Reads may be steadily unsupported (e.g. serial has no UCSI peer); the
// Fetched cells carry the error to the UI, so we don't warn every tick.
let version = self.source.get_ucsi_version();
let capability = self.source.get_ucsi_capability();
let connector_capability = self.source.get_ucsi_connector_capability(UCSI_CONNECTOR);
The merge-base changed after approval.
6ef05cb to
d5d0cfa
Compare
Add a read-only host UCSI slice so ec-test-lib and the ec-test-tui Ratatui app can query the secure-world UCSI stub over ACPI. ec-test-lib: - New platform-neutral `ucsi` module: small value types (version, capability, connector capability/status, CCI) plus 48-byte mailbox decoding that validates VERSION, CCI and the response data length. Kept off the Windows-only path so decode is unit-tested on Linux. - `UcsiSource` trait (get_version, get_capability, get_connector_capability, get_connector_status) added to the `Source` supertrait with an `Arc` forwarding impl. - Mock returns deterministic single-connector PD-sink fixtures. - Serial gains an `Unsupported` error (mapped to `ErrorKind::Other`) as it has no EC-side UCSI peer; it never fakes success. - Windows Acpi backend evaluates `\_SB.ECT0.USND` with an 8-byte CONTROL buffer and decodes the returned 48-byte mailbox. ec-test-tui: - Extend `DynSource` and the manual battery/thermal test doubles. - Add `UcsiState`/`UcsiUpdater` and a compact, stateless USB-C tab plus dashboard card modeled on the RTC module (version, connector 1 capability, connected sink status). Errors render honestly. Assisted-by: GitHub Copilot:claude-opus-4.8 Copilot-Session: 6cb7060d-6d47-49ad-a710-428fe4c2f3dc
Apply the independent code-judo findings, cutting LOC and concepts while preserving behavior and the unique tests. ec-test-lib: - Replace the public `Mailbox` + `Cci` intermediate types with two private helpers (`validate` / `message_in`) plus free `decode_*` functions. They enforce 48-byte length, VERSION 0x0120, cmd_complete, no error/not_supported, and the expected data length, then decode each response directly. - Flatten `UcsiConnectorCapability` (drop the `OperationMode` wrapper) and drop the unused CCI `busy` accessor and capability Type-C version field. `UcsiVersion` is retained since Source/TUI consume it. - Delete the duplicate Mock tests that mirrored the fixture constants; the retained updater test already exercises the Mock values. ec-test-tui: - Collapse the UCSI UI to one shared metric-row builder used by both the tab and the dashboard card; remove the dedicated panel renderers and redundant formatting helpers. Pending/error text stays honest. - Stop warning every poll for the steadily-unsupported serial backend; the Fetched error cells still surface the failure to the UI. - Give `DynSource` default UCSI methods so the battery/thermal test doubles need no stubs, reverting those files to pristine. - Drop the UI formatting tests that only mirrored string output. Assisted-by: GitHub Copilot:claude-opus-4.8 Copilot-Session: 6cb7060d-6d47-49ad-a710-428fe4c2f3dc
Keep mailbox VERSION reporting forward-compatible while retaining the UCSI 1.2 gate for command-specific payload decoders. Clarify connector and USB-PD capability text in the TUI. Assisted-by: GitHub Copilot:gpt-5.6-sol Copilot-Session: 6cb7060d-6d47-49ad-a710-428fe4c2f3dc
Replace the hand-rolled UCSI value types and manual response bit decoding with the upstream embedded-usb-pd v1.2 shapes, so the host slice shares one source of truth with the secure-world PPM stub. - Pin embedded-usb-pd at bc8c582 with the `ucsi-v1_2` feature and add a direct bincode 2.0.1 (default-features=false) dependency to decode the GET_CAPABILITY payload with fixed-int encoding. - ec/test-lib/src/ucsi.rs keeps only the 48-byte envelope validation (length, forward-compatible VERSION, CCI via LocalCci, data length) and the UcsiVersion newtype. UcsiCapability/UcsiConnectorCapability/ UcsiConnectorStatus/PowerDirection are now re-exports/aliases of the upstream response types; decode_* build them via bincode, From<u16>, and ResponseData::try_from([u8; 11]). Payload decode failures collapse to a single MailboxError::PayloadDecode variant, keeping bincode out of the public API. - control() takes the upstream CommandType; ACPI callers updated. - Mock, TUI rendering, and the updater test consume the upstream types directly; the TUI keeps its small projection (version, connector, connected sink status) and honest pending/error text. - cargo-vet: exempt the newly introduced bitfield 0.19.5, bitfield-macros 0.19.5, and syn 3.0.3 (bincode/embedded-usb-pd are covered by imported OpenDevicePartnership audits); the bincode RustSec ignore is retained. Assisted-by: GitHub Copilot:claude-opus-4.8 Copilot-Session: 6cb7060d-6d47-49ad-a710-428fe4c2f3dc
Implement the UCSI source trait for the upstream Windows class-driver backend with explicit unsupported results. This preserves the existing Windows source after rebasing while reserving UCSI access for the ACPI test backend. Assisted-by: GitHub Copilot:gpt-5.6-sol Copilot-Session: 6cb7060d-6d47-49ad-a710-428fe4c2f3dc
d5d0cfa to
4c87111
Compare
Windows returns the complete 144-byte fixed-hardware operation-region envelope from ECT0.USND. Extract the 48-byte FF-A payload before decoding the UCSI mailbox, while retaining direct-mailbox support for tests and other callers. Assisted-by: GitHub Copilot:gpt-5.6-sol Copilot-Session: 6cb7060d-6d47-49ad-a710-428fe4c2f3dc
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 17 changed files in this pull request and generated no new comments.
Suppressed comments (2)
ec/test-tui/src/source.rs:63
- The default UCSI methods all return the same generic error ("UCSI not supported by this source"), so the UI will show identical error text for version/capability/connector fields. Making each default error include the specific operation name would provide clearer UI feedback without affecting callers.
fn get_ucsi_version(&self) -> Result<UcsiVersion> {
Err(eyre!("UCSI not supported by this source"))
}
fn get_ucsi_capability(&self) -> Result<UcsiCapability> {
Err(eyre!("UCSI not supported by this source"))
ec/test-lib/src/acpi.rs:729
get_version()issues a GET_CAPABILITY ACPI command, andget_capability()issues the same GET_CAPABILITY command again. Since the TUI updater calls both every tick, this doubles the ACPI method traffic for no additional mailbox reads. Consider caching the mailbox result per tick or caching the version (e.g., OnceLock) soget_version()does not need to re-evaluate\_SB.ECT0.USND.
fn get_version(&self) -> Result<UcsiVersion, Self::Error> {
let mailbox = self.ucsi_command(ucsi::control(ucsi::CommandType::GetCapability, 0))?;
Ok(ucsi::decode_version(&mailbox)?)
}
Validate the status word in the 144-byte Windows fixed-hardware envelope before decoding its UCSI payload so transport failures retain their actual firmware status. Assisted-by: GitHub Copilot:gpt-5.6-sol Copilot-Session: 6cb7060d-6d47-49ad-a710-428fe4c2f3dc
Pull request was converted to draft
Summary
UcsiSourceabstractionECT0.USNDScope
Supports only UCSI version, capability, connector-capability, and connector-status reads for the deterministic one-connector stub. No CLI, notifications, or native UCSI class-driver integration.
Validation
Windows E2E limitation
The current public ARM64 ValidationOS image is build
26100.8972. It can load and invoke the ACPI backend, but its kernel/ACPI stack does not expose the FF-A interface introduced in the 10.0.28000/26H1 line, soFFixedHwevaluation fails withERROR_ACPI_ERROR (669)before secure world is reached. The host-side direct-mailbox/envelope parsing is covered by tests; full Windows ACPI -> FF-A execution requires a 28000-class image. Evidence: OpenDevicePartnership/odp-platform-qemu-arm-virt#41 (comment).Related