Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 44 additions & 0 deletions embedded-service/src/type_c/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,25 @@ impl PortResponseData {
/// Port-specific command response
pub type PortResponse = Result<PortResponseData, PdError>;

/// System power state for Sx App Config register.
///
/// Used to notify the PD controller of the current system power state,
/// which triggers Application Configuration updates (e.g., crossbar reconfiguration).
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum SystemPowerState {
/// S0 - System fully running
S0,
/// S3 - Suspend to RAM
S3,
/// S4 - Hibernate
S4,
/// S5 - Soft off
S5,
/// S0ix - Modern standby / Connected standby
S0ix,
}

/// PD controller command-specific data
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
Expand All @@ -386,6 +405,8 @@ pub enum InternalCommandData {
Status,
/// Sync controller state
SyncState,
/// Set the system power state
SetSystemPowerState(SystemPowerState),
}

/// PD controller command
Expand Down Expand Up @@ -680,6 +701,12 @@ pub trait Controller {
port: LocalPortId,
reconnect_time_s: Option<NonZeroU8>,
) -> impl Future<Output = Result<(), Error<Self::BusError>>>;

/// Set the system power state on the controller.
///
/// This notifies the PD controller of the current system power state,
/// which triggers Application Configuration updates (e.g., crossbar reconfiguration).
fn set_power_state(&mut self, state: SystemPowerState) -> impl Future<Output = Result<(), Error<Self::BusError>>>;
}

/// Internal context for managing PD controllers
Expand Down Expand Up @@ -1082,6 +1109,23 @@ impl ContextToken {
}
}

/// Set the system power state on the given controller.
///
/// This notifies the PD controller of the current system power state,
/// which triggers Application Configuration updates (e.g., crossbar reconfiguration).
pub async fn set_power_state(&self, controller_id: ControllerId, state: SystemPowerState) -> Result<(), PdError> {
match self
.send_controller_command(controller_id, InternalCommandData::SetSystemPowerState(state))
.await?
{
InternalResponseData::Complete => Ok(()),
r => {
error!("Invalid response: expected complete, got {:?}", r);
Err(PdError::InvalidResponse)
}
}
}

/// Wait for an external command
pub async fn wait_external_command(
&self,
Expand Down
21 changes: 20 additions & 1 deletion embedded-service/src/type_c/external.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use embedded_usb_pd::{GlobalPortId, LocalPortId, PdError, ucsi};
use crate::type_c::{
Cached,
controller::{
PdStateMachineConfig, TbtConfig, TypeCStateMachineState, UsbControlConfig, execute_external_ucsi_command,
PdStateMachineConfig, SystemPowerState, TbtConfig, TypeCStateMachineState, UsbControlConfig,
execute_external_ucsi_command,
},
};

Expand All @@ -28,6 +29,8 @@ pub enum ControllerCommandData {
SyncState,
/// Controller reset
Reset,
/// Set the system power state
SetSystemPowerState(SystemPowerState),
}

/// Controller-specific commands
Expand Down Expand Up @@ -309,6 +312,22 @@ pub async fn sync_controller_state(id: ControllerId) -> Result<(), PdError> {
}
}

/// Set the system power state on the given controller.
///
/// This notifies the PD controller of the current system power state,
/// which triggers Application Configuration updates (e.g., crossbar reconfiguration).
pub async fn set_power_state(id: ControllerId, state: SystemPowerState) -> Result<(), PdError> {
match execute_external_controller_command(Command::Controller(ControllerCommand {
id,
data: ControllerCommandData::SetSystemPowerState(state),
}))
.await?
{
ControllerResponseData::Complete => Ok(()),
_ => Err(PdError::InvalidResponse),
}
}

/// Get number of ports on the system
pub fn get_num_ports() -> usize {
super::controller::get_num_ports()
Expand Down
4 changes: 2 additions & 2 deletions examples/rt685s-evk/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions examples/std/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions examples/std/src/bin/type_c/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ mod test_controller {
info!("Sync controller state");
Ok(controller::InternalResponseData::Complete)
}
controller::InternalCommandData::SetSystemPowerState(state) => {
info!("Set system power state: {state:?}");
Ok(controller::InternalResponseData::Complete)
}
}
}

Expand Down
7 changes: 6 additions & 1 deletion examples/std/src/lib/type_c/mock_controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use embedded_services::{
type_c::{
controller::{
AttnVdm, ControllerStatus, DpConfig, DpPinConfig, DpStatus, OtherVdm, PdStateMachineConfig, PortStatus,
RetimerFwUpdateState, SendVdm, TbtConfig, TypeCStateMachineState, UsbControlConfig,
RetimerFwUpdateState, SendVdm, SystemPowerState, TbtConfig, TypeCStateMachineState, UsbControlConfig,
},
event::PortEvent,
},
Expand Down Expand Up @@ -331,6 +331,11 @@ impl embedded_services::type_c::controller::Controller for Controller<'_> {
debug!("Execute electrical disconnect for port {port:?} with reconnect time {reconnect_time_s:?}");
Ok(())
}

async fn set_power_state(&mut self, state: SystemPowerState) -> Result<(), Error<Self::BusError>> {
debug!("Set power state: {state:?}");
Ok(())
}
}

pub struct Validator;
Expand Down
19 changes: 19 additions & 0 deletions type-c-service/src/driver/tps6699x.rs
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,25 @@ impl<M: RawMutex, B: I2c> Controller for Tps6699x<'_, M, B> {
}
}
}

async fn set_power_state(&mut self, state: controller::SystemPowerState) -> Result<(), Error<Self::BusError>> {
use tps6699x::registers::SystemPowerState as DriverSystemPowerState;

let driver_state = match state {
controller::SystemPowerState::S0 => DriverSystemPowerState::S0,
controller::SystemPowerState::S3 => DriverSystemPowerState::S3,
controller::SystemPowerState::S4 => DriverSystemPowerState::S4,
controller::SystemPowerState::S5 => DriverSystemPowerState::S5,
controller::SystemPowerState::S0ix => DriverSystemPowerState::S0Ix,
};
Comment thread
asasine marked this conversation as resolved.
Resolved

// The TRM indicates this register is unique per port, so write to all ports
for port_idx in 0..self.port_events.len() {
let port = LocalPortId(port_idx as u8);
self.tps6699x.set_sx_app_config(port, driver_state).await?;
}
Ok(())
}
}

impl<'a, M: RawMutex, BUS: I2c> AsRef<tps6699x_drv::Tps6699x<'a, M, BUS>> for Tps6699x<'a, M, BUS> {
Expand Down
17 changes: 17 additions & 0 deletions type-c-service/src/service/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,19 @@ impl<'a> Service<'a> {
external::Response::Controller(status.map(|_| external::ControllerResponseData::Complete))
}

/// Process external controller set power state command
pub(super) async fn process_external_controller_set_power_state(
&self,
controller: ControllerId,
state: embedded_services::type_c::controller::SystemPowerState,
) -> external::Response<'static> {
let status = self.context.set_power_state(controller, state).await;
if let Err(e) = status {
error!("Error setting power state: {:#?}", e);
}
external::Response::Controller(status.map(|_| external::ControllerResponseData::Complete))
}

/// Process external controller commands
pub(super) async fn process_external_controller_command(
&self,
Expand All @@ -55,6 +68,10 @@ impl<'a> Service<'a> {
ControllerCommandData::ControllerStatus => self.process_external_controller_status(command.id).await,
ControllerCommandData::SyncState => self.process_external_controller_sync_state(command.id).await,
ControllerCommandData::Reset => self.process_external_controller_reset(command.id).await,
ControllerCommandData::SetSystemPowerState(state) => {
self.process_external_controller_set_power_state(command.id, state)
.await
}
}
}
}
8 changes: 8 additions & 0 deletions type-c-service/src/wrapper/pd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,14 @@ where
.map_err(|_| PdError::Failed),
)
}
controller::InternalCommandData::SetSystemPowerState(power_state) => {
let result = controller.set_power_state(*power_state).await;
controller::Response::Controller(
result
.map(|_| InternalResponseData::Complete)
.map_err(|_| PdError::Failed),
)
}
}
}

Expand Down
Loading