diff --git a/power-policy-service/src/lib.rs b/power-policy-service/src/lib.rs index c43719f8..bd463bc3 100644 --- a/power-policy-service/src/lib.rs +++ b/power-policy-service/src/lib.rs @@ -12,6 +12,8 @@ pub mod provider; pub mod task; pub use config::Config; + +use crate::provider::PowerState; pub mod charger; const MAX_CONNECTED_PROVIDERS: usize = 4; @@ -106,6 +108,22 @@ impl PowerPolicy { /// Returns true if the device was operating as a provider async fn remove_connected_provider(&self, device_id: DeviceId) -> bool { if self.state.lock().await.connected_providers.remove(&device_id) { + // Determine total requested power draw + let mut total_power_mw = 0; + for device in self.context.devices().iter_only::() { + total_power_mw += device + .provider_capability() + .await + .map_or(0, |cap| cap.capability.max_power_mw()); + } + + self.state.lock().await.current_provider_state.state = + if total_power_mw > self.config.limited_power_threshold_mw { + PowerState::Limited + } else { + PowerState::Unlimited + }; + self.comms_notify(CommsMessage { data: CommsData::ProviderDisconnected(device_id), }) diff --git a/power-policy-service/src/provider.rs b/power-policy-service/src/provider.rs index 83050957..2b31c163 100644 --- a/power-policy-service/src/provider.rs +++ b/power-policy-service/src/provider.rs @@ -22,7 +22,7 @@ pub enum PowerState { #[derive(Clone, Copy, Default)] pub(super) struct State { /// Current power state - state: PowerState, + pub state: PowerState, } impl PowerPolicy { diff --git a/type-c-service/src/driver/tps6699x.rs b/type-c-service/src/driver/tps6699x.rs index 6e78becd..64761648 100644 --- a/type-c-service/src/driver/tps6699x.rs +++ b/type-c-service/src/driver/tps6699x.rs @@ -372,7 +372,8 @@ impl Controller for Tps6699x<'_, M, B> { port_status.dual_power = source_pdos[0].dual_role_power(); port_status.unconstrained_power = source_pdos[0].unconstrained_power(); } - } else if pd_status.is_source() { + } else if status.port_role() { + // port_role is true for source // Implicit source contract let current = TypecCurrent::try_from(port_control.typec_current()).map_err(Error::Pd)?; debug!("Port{} type-C source current: {:#?}", port.0, current); diff --git a/type-c-service/src/wrapper/mod.rs b/type-c-service/src/wrapper/mod.rs index 73846318..db89ae8e 100644 --- a/type-c-service/src/wrapper/mod.rs +++ b/type-c-service/src/wrapper/mod.rs @@ -237,6 +237,11 @@ where .lookup_global_port(local_port_id) .map_err(Error::Pd)?; + let previous_status = state + .port_states() + .get(local_port_id.0 as usize) + .ok_or(Error::Pd(PdError::InvalidPort))? + .status; let status = controller.get_port_status(local_port_id).await?; trace!("Port{} status: {:#?}", global_port_id.0, status); @@ -289,7 +294,7 @@ where self.process_new_consumer_contract(power, &status).await?; } - if status_event.new_power_contract_as_provider() { + if status.is_connected() && status.available_source_contract != previous_status.available_source_contract { self.process_new_provider_contract(power, &status).await?; }