Skip to content

Add host UCSI source and USB-C TUI tab - #162

Draft
dymk wants to merge 7 commits into
OpenDevicePartnership:mainfrom
dymk:dymk/ucsi-test-stub
Draft

Add host UCSI source and USB-C TUI tab#162
dymk wants to merge 7 commits into
OpenDevicePartnership:mainfrom
dymk:dymk/ucsi-test-stub

Conversation

@dymk

@dymk dymk commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add a platform-neutral UCSI mailbox decoder and UcsiSource abstraction
  • add deterministic mock and Windows ACPI implementations for ECT0.USND
  • normalize either a direct 48-byte mailbox or the 144-byte Windows FF-A envelope
  • surface non-zero FF-A transport status explicitly
  • report serial UCSI as explicitly unsupported
  • add a compact Ratatui USB-C tab and dashboard card

Scope

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

  • ec-test-lib and ec-test-tui tests
  • stable/beta clippy and formatting
  • Windows ARM64 ACPI backend check
  • cargo-deny and cargo-vet
  • independent correctness and code-judo reviews
  • direct QEMU FF-A UCSI routing smoke: 7 passed, 0 failed
  • all GitHub checks passing

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, so FFixedHw evaluation fails with ERROR_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

@dymk
dymk marked this pull request as ready for review August 4, 2026 20:15
@dymk
dymk requested a review from a team as a code owner August 4, 2026 20:15
@dymk
dymk requested review from kat-perez, kurtjd, maxperga-msft and philgweber and a lite review from Copilot August 4, 2026 20:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 + UcsiSource trait in ec-test-lib, with Windows ACPI and mock implementations and explicit serial “unsupported” errors.
  • Adds a UcsiUpdater and shared UcsiState to 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.

Comment thread ec/test-tui/src/ucsi.rs Outdated
Comment thread ec/test-lib/src/ucsi.rs
Comment thread ec/test-lib/src/ucsi.rs Outdated
Copilot AI review requested due to automatic review settings August 5, 2026 19:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 13 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings August 5, 2026 19:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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() polls get_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 when state.version is still None (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);

philgweber
philgweber previously approved these changes Aug 5, 2026
@dymk
dymk dismissed philgweber’s stale review August 5, 2026 21:28

The merge-base changed after approval.

Copilot AI review requested due to automatic review settings August 6, 2026 16:54
@dymk
dymk force-pushed the dymk/ucsi-test-stub branch from 6ef05cb to d5d0cfa Compare August 6, 2026 16:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 17 changed files in this pull request and generated no new comments.

dymk added 5 commits August 7, 2026 17:54
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
@dymk
dymk force-pushed the dymk/ucsi-test-stub branch from d5d0cfa to 4c87111 Compare August 7, 2026 17:55
Copilot AI review requested due to automatic review settings August 7, 2026 17:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 17 changed files in this pull request and generated no new comments.

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
Copilot AI review requested due to automatic review settings August 7, 2026 22:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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, and get_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) so get_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
Copilot AI review requested due to automatic review settings August 7, 2026 23:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 17 changed files in this pull request and generated no new comments.

@dymk
dymk requested a review from philgweber August 8, 2026 02:29
@dymk
dymk enabled auto-merge (squash) August 8, 2026 03:25
@dymk
dymk marked this pull request as draft August 8, 2026 07:01
auto-merge was automatically disabled August 8, 2026 07:01

Pull request was converted to draft

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants