type-c-service: add power swap functionality and testing#917
Conversation
6428009 to
8ecf60a
Compare
There was a problem hiding this comment.
Pull request overview
Summary of changes
This PR adds explicit handling for USB-PD power role swaps in the Type-C controller so that the previous power role is torn down before the new-role contract is established. On a power_swap_completed status event, the port now transitions its local PSU tracking back to Idle, disables the sink path when swapping away from a consumer role, and notifies the power policy of a disconnect so it can accept the subsequent connect in the new role. The PR also adds integration-style tests to validate both swap directions and to ensure the power policy observes a disconnect -> connect sequence across the swap. This directly addresses the reported issue where the power policy rejected the new-role connection because the old role was never cleared.
Changes:
- Add
process_power_role_swap()to tear down the prior consumer/provider contract onpower_swap_completedbefore the next contract connects. - Wire role-swap handling into the port status-changed processing pipeline.
- Add integration tests for consumer→provider and provider→consumer swaps, asserting expected PSU state transitions and power-policy broadcasts.
Step-by-step review guide
-
Role swap teardown in the controller
process_power_role_swap()is invoked onpower_swap_completedand only acts if the port remains connected and the local PSU state indicates an active connected role.- Key behavior: when swapping away from consumer, it calls
enable_sink_path(..., false)to safely stop consumption; then it resets the localpsu_stateback toIdle(clearing caps) and emitspower_policy_interface::psu::event::EventData::Disconnected(...)so the power policy stops tracking the old role.
-
Event ordering in
process_port_status_changed- The swap teardown is intentionally processed before any “new contract” handling (
sink_readyconsumer contract path, and provider contract change detection). This ordering is what allows the subsequent contract event to be accepted as a fresh connect in the new role.
- The swap teardown is intentionally processed before any “new contract” handling (
-
Test coverage for both swap directions
- The new tests model: initial plug + contract →
power_swap_completed→ new contract, and assert:- the intermediate
psu_statebecomesIdleafter swap completion, and - the power policy broadcasts
*Disconnectedfollowed by*Connectedfor the new role.
- the intermediate
- Non-obvious detail: the tests are integration-style (they run the Type-C service task + power policy task concurrently), so correct behavior depends on both the controller emitting the right PSU events and the power-policy service interpreting them as intended.
- The new tests model: initial plug + contract →
Potential issues
| # | Severity | File | Description | Code |
|---|---|---|---|---|
| 1 | Medium | type-c-service/tests/power.rs:611-613 |
The consumer→provider role-swap test doesn’t assert that the sink path was actually disabled during the swap. Because the harness doesn’t verify unused mock expectations, this test can still pass even if process_power_role_swap stops calling enable_sink_path(..., false) (a key behavior described in the PR). |
assert_eq!(port0.port.lock().await.state().psu_state, PsuState::Idle); |
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| type-c-service/src/controller/power.rs | Adds process_power_role_swap() to tear down the old role and notify power policy on swap completion. |
| type-c-service/src/controller/mod.rs | Invokes role-swap teardown when power_swap_completed is present in the status event bitfield. |
| type-c-service/tests/power.rs | Adds integration tests for consumer→provider and provider→consumer swap flows (disconnect → connect, PSU state transitions). |
8ecf60a to
35c40e2
Compare
Handle USB-PD power role swaps in the Type-C port and add test coverage.
Previously the port never tore down the old role on a swap, so the power policy rejected the new-role connection. Now
process_power_role_swapruns on apower_swap_completedevent:psu_statetoIdle, andThe next contract event connects the new role.
Tests cover both swap directions (plug + contract ->
power_swap_completed-> new contract), asserting thepsu_statetransitions and thedisconnect -> connectpower-policy broadcasts.Assisted-by: GitHub Copilot:claude-opus-4.8
Resolves #831