Skip to content

Commit 2da8466

Browse files
authored
Merge pull request #291 from RobertZ2011:pd-controller-init
type-c: Add function to sync controller state
2 parents 6aabfe6 + 1ec8a7b commit 2da8466

File tree

4 files changed

+67
-20
lines changed

4 files changed

+67
-20
lines changed

embedded-service/src/type_c/controller.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,11 @@ impl<'a> Device<'a> {
219219
}
220220
}
221221

222+
/// Get the controller ID
223+
pub fn id(&self) -> ControllerId {
224+
self.id
225+
}
226+
222227
/// Send a command to this controller
223228
pub async fn send_command(&self, command: Command) -> Response {
224229
self.command.send(command).await;
@@ -302,6 +307,8 @@ pub trait Controller {
302307
/// Type of error returned by the bus
303308
type BusError;
304309

310+
/// Ensure software state is in sync with hardware state
311+
fn sync_state(&mut self) -> impl Future<Output = Result<(), Error<Self::BusError>>>;
305312
/// Returns ports with pending events
306313
fn wait_port_event(&mut self) -> impl Future<Output = Result<(), Error<Self::BusError>>>;
307314
/// Returns and clears current events for the given port

examples/std/src/bin/type_c/service.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ mod test_controller {
9696
impl embedded_services::type_c::controller::Controller for Controller<'_> {
9797
type BusError = ();
9898

99+
async fn sync_state(&mut self) -> Result<(), Error<Self::BusError>> {
100+
Ok(())
101+
}
102+
99103
async fn wait_port_event(&mut self) -> Result<(), Error<Self::BusError>> {
100104
trace!("Wait for port event");
101105
let events = self.state.events.wait().await;

type-c-service/src/driver/tps6699x.rs

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ impl<'a, const N: usize, M: RawMutex, B: I2c> Tps6699x<'a, N, M, B> {
4646
tps6699x: &mut tps6699x::Tps6699x<'a, M, B>,
4747
port: LocalPortId,
4848
) -> Result<PortEventKind, Error<B::Error>> {
49-
#[allow(unused_mut)]
5049
let mut events = PortEventKind::none();
50+
let previous_status = self.port_status[port.0 as usize].get();
5151

5252
let status = tps6699x.get_port_status(port).await?;
5353
trace!("Port{} status: {:#?}", port.0, status);
@@ -95,13 +95,6 @@ impl<'a, const N: usize, M: RawMutex, B: I2c> Tps6699x<'a, N, M, B> {
9595
let current = TypecCurrent::try_from(port_control.typec_current()).map_err(Error::Pd)?;
9696
debug!("Port{} type-C source current: {:#?}", port.0, current);
9797
let new_contract = Some(PowerCapability::from(current));
98-
99-
if new_contract != port_status.available_source_contract {
100-
debug!("New implicit contract as provider");
101-
// We don't get interrupts for implicit contracts so generate event manually
102-
events.set_new_power_contract_as_provider(true);
103-
}
104-
10598
port_status.available_source_contract = new_contract;
10699
} else {
107100
// Implicit sink contract
@@ -115,13 +108,6 @@ impl<'a, const N: usize, M: RawMutex, B: I2c> Tps6699x<'a, N, M, B> {
115108
debug!("Port{} type-C sink current: {:#?}", port.0, current);
116109
Some(PowerCapability::from(current))
117110
};
118-
119-
if new_contract.is_some() && new_contract != port_status.available_sink_contract {
120-
debug!("New implicit contract as consumer");
121-
// We don't get interrupts for implicit contracts so generate event manually
122-
events.set_new_power_contract_as_consumer(true);
123-
}
124-
125111
port_status.available_sink_contract = new_contract;
126112
}
127113

@@ -146,6 +132,20 @@ impl<'a, const N: usize, M: RawMutex, B: I2c> Tps6699x<'a, N, M, B> {
146132
debug!("Port{} power path: {:#?}", port.0, port_status.power_path);
147133
}
148134

135+
if port_status.available_sink_contract.is_some()
136+
&& port_status.available_sink_contract != previous_status.available_sink_contract
137+
{
138+
debug!("Port{}: new sink contract", port.0);
139+
events.set_new_power_contract_as_consumer(true);
140+
}
141+
142+
if port_status.available_source_contract.is_some()
143+
&& port_status.available_source_contract != previous_status.available_source_contract
144+
{
145+
debug!("Port{}: new source contract", port.0);
146+
events.set_new_power_contract_as_provider(true);
147+
}
148+
149149
self.port_status[port.0 as usize].set(port_status);
150150
Ok(events)
151151
}
@@ -186,7 +186,6 @@ impl<'a, const N: usize, M: RawMutex, B: I2c> Tps6699x<'a, N, M, B> {
186186
}
187187

188188
/// Signal an event on the given port
189-
#[allow(dead_code)]
190189
fn signal_event(&self, port: LocalPortId, event: PortEventKind) {
191190
if port.0 >= self.port_events.len() as u8 {
192191
return;
@@ -202,6 +201,19 @@ impl<'a, const N: usize, M: RawMutex, B: I2c> Tps6699x<'a, N, M, B> {
202201
impl<const N: usize, M: RawMutex, B: I2c> Controller for Tps6699x<'_, N, M, B> {
203202
type BusError = B::Error;
204203

204+
/// Controller specific initialization
205+
#[allow(clippy::await_holding_refcell_ref)]
206+
async fn sync_state(&mut self) -> Result<(), Error<Self::BusError>> {
207+
for i in 0..N {
208+
let port = LocalPortId(i as u8);
209+
let mut tps6699x = self.tps6699x.borrow_mut();
210+
let event = self.update_port_status(&mut tps6699x, port).await?;
211+
self.signal_event(port, event);
212+
}
213+
214+
Ok(())
215+
}
216+
205217
/// Wait for an event on any port
206218
#[allow(clippy::await_holding_refcell_ref)]
207219
async fn wait_port_event(&mut self) -> Result<(), Error<Self::BusError>> {

type-c-service/src/wrapper/mod.rs

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use embedded_services::power::policy::device::StateKind;
88
use embedded_services::power::policy::{self, action};
99
use embedded_services::type_c::controller::{self, Controller, PortStatus};
1010
use embedded_services::type_c::event::{PortEventFlags, PortEventKind};
11-
use embedded_services::{error, info, intrusive_list, trace, warn};
11+
use embedded_services::{error, info, trace, warn};
1212
use embedded_usb_pd::{type_c::Current as TypecCurrent, Error, PdError, PortId as LocalPortId};
1313

1414
mod pd;
@@ -42,6 +42,13 @@ impl<'a, const N: usize, C: Controller> ControllerWrapper<'a, N, C> {
4242
}
4343
}
4444

45+
/// Ensure the software state is in sync with the hardware state
46+
#[allow(clippy::await_holding_refcell_ref)]
47+
async fn sync_state(&self) -> Result<(), Error<C::BusError>> {
48+
let mut controller = self.controller.borrow_mut();
49+
controller.sync_state().await
50+
}
51+
4552
/// Handle a plug event
4653
async fn process_plug_event(
4754
&self,
@@ -211,11 +218,28 @@ impl<'a, const N: usize, C: Controller> ControllerWrapper<'a, N, C> {
211218
}
212219

213220
/// Register all devices with their respective services
214-
pub async fn register(&'static self) -> Result<(), intrusive_list::Error> {
221+
pub async fn register(&'static self) -> Result<(), Error<C::BusError>> {
215222
for device in &self.power {
216-
policy::register_device(device).await?
223+
policy::register_device(device).await.map_err(|_| {
224+
error!(
225+
"Controller{}: Failed to register power device {}",
226+
self.pd_controller.id().0,
227+
device.id().0
228+
);
229+
Error::Pd(PdError::Failed)
230+
})?;
217231
}
218232

219-
controller::register_controller(&self.pd_controller).await
233+
controller::register_controller(&self.pd_controller)
234+
.await
235+
.map_err(|_| {
236+
error!(
237+
"Controller{}: Failed to register PD controller",
238+
self.pd_controller.id().0
239+
);
240+
Error::Pd(PdError::Failed)
241+
})?;
242+
243+
self.sync_state().await
220244
}
221245
}

0 commit comments

Comments
 (0)