Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
18 changes: 13 additions & 5 deletions examples/rt685s-evk/src/bin/type_c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ type PortType = Mutex<
'static,
Tps6699xMutex<'static>,
SharedStateType,
DynamicSender<'static, type_c_interface::service::event::PortEventData>,
type_c_interface::port::event::NonBlockingSenderNotifier<
DynamicSender<'static, type_c_interface::service::event::PortEventData>,
>,
PowerNotifier<'static>,
DynamicSender<'static, type_c_service::controller::event::Loopback>,
>,
Expand Down Expand Up @@ -91,9 +93,15 @@ type TypeCServiceEventReceiverType = type_c_service::service::event_receiver::Ar
PowerPolicyReceiverType,
>;

type TypeCServiceSenderType = NoopSender;
type TypeCRegistrationType =
type_c_service::service::registration::ArrayRegistration<'static, PortType, PORT_COUNT, TypeCServiceSenderType, 1>;
type TypeCServiceNotifierType =
type_c_interface::service::event::NonBlockingSenderNotifier<'static, PortType, NoopSender>;
type TypeCRegistrationType = type_c_service::service::registration::ArrayRegistration<
'static,
PortType,
PORT_COUNT,
TypeCServiceNotifierType,
1,
>;
type TypeCServiceType = type_c_service::service::Service<'static, TypeCRegistrationType>;
type PortEventReceiverType = PortEventReceiver<
'static,
Expand Down Expand Up @@ -245,7 +253,7 @@ async fn main(spawner: Spawner) {
Default::default(),
TypeCRegistrationType {
ports: [port0, port1],
service_senders: [NoopSender],
service_notifiers: [NoopSender.into()],
port_data: [
PortData {
local_port: Some(LocalPortId(0)),
Expand Down
18 changes: 13 additions & 5 deletions examples/rt685s-evk/src/bin/type_c_cfu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ type PortType = Mutex<
'static,
Tps6699xMutex<'static>,
PortSharedStateType,
DynamicSender<'static, type_c_interface::service::event::PortEventData>,
type_c_interface::port::event::NonBlockingSenderNotifier<
DynamicSender<'static, type_c_interface::service::event::PortEventData>,
>,
PowerNotifier<'static>,
DynamicSender<'static, type_c_service::controller::event::Loopback>,
>,
Expand Down Expand Up @@ -107,9 +109,15 @@ type TypeCServiceEventReceiverType = type_c_service::service::event_receiver::Ar
PowerPolicyReceiverType,
>;

type TypeCServiceSenderType = NoopSender;
type TypeCRegistrationType =
type_c_service::service::registration::ArrayRegistration<'static, PortType, PORT_COUNT, TypeCServiceSenderType, 1>;
type TypeCServiceNotifierType =
type_c_interface::service::event::NonBlockingSenderNotifier<'static, PortType, NoopSender>;
type TypeCRegistrationType = type_c_service::service::registration::ArrayRegistration<
'static,
PortType,
PORT_COUNT,
TypeCServiceNotifierType,
1,
>;
type TypeCServiceType = type_c_service::service::Service<'static, TypeCRegistrationType>;
type PortEventReceiverType = PortEventReceiver<
'static,
Expand Down Expand Up @@ -391,7 +399,7 @@ async fn main(spawner: Spawner) {
local_port: Some(LocalPortId(1)),
},
],
service_senders: [NoopSender],
service_notifiers: [NoopSender.into()],
},
)));

Expand Down
4 changes: 3 additions & 1 deletion examples/std/src/lib/type_c/mock_controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,9 @@ pub type Port<'a> = type_c_service::controller::Port<
'a,
Mutex<GlobalRawMutex, Controller<'a>>,
Mutex<GlobalRawMutex, SharedState>,
channel::DynamicSender<'a, type_c_interface::service::event::PortEventData>,
type_c_interface::port::event::NonBlockingSenderNotifier<
channel::DynamicSender<'a, type_c_interface::service::event::PortEventData>,
>,
PowerNotifier<'a>,
channel::DynamicSender<'a, type_c_service::controller::event::Loopback>,
>;
134 changes: 133 additions & 1 deletion type-c-interface/src/port/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,17 @@
//! Consequently [`PortNotificationEventBitfield`] implements iterator traits to allow for processing these events as a stream.
use bitfield::bitfield;

use core::future::ready;

use embedded_services::event::{NonBlockingSender, Sender};
use embedded_usb_pd::ado::Ado;

use crate::control::dp::DpStatus;
use crate::control::pd::PortStatus;
use crate::control::vdm::AttnVdm;
use crate::control::vdm::OtherVdm;

use crate::port::notification::{Error as NotificationError, Notifier};
use crate::service::event::{PortEventData, StatusChangedData};
bitfield! {
/// Raw bitfield of possible port status events
#[derive(Copy, Clone, PartialEq, Eq, Default)]
Expand Down Expand Up @@ -404,6 +412,130 @@ impl From<PortNotificationEventBitfield> for PortEventBitfield {
}
}

/// New-type that implements the [`Notifier`] trait for any [`NonBlockingSender<PortEventData>`].
///
/// This allows the user to choose blocking/non-blocking behavior when a type supports both.
pub struct NonBlockingSenderNotifier<S: NonBlockingSender<PortEventData>>(pub S);

impl<S: NonBlockingSender<PortEventData>> Notifier for NonBlockingSenderNotifier<S> {
fn notify_status_changed(
&mut self,
status_event: PortStatusEventBitfield,
previous_status: PortStatus,
current_status: PortStatus,
) -> impl Future<Output = Result<(), NotificationError>> {
ready(
self.0
.try_send(PortEventData::StatusChanged(StatusChangedData {
status_event,
previous_status,
current_status,
}))
.ok_or(NotificationError::WouldBlock),
)
}

fn notify_alert(&mut self, alert: Ado) -> impl Future<Output = Result<(), NotificationError>> {
ready(
self.0
.try_send(PortEventData::Alert(alert))
.ok_or(NotificationError::WouldBlock),
)
}

fn notify_vdm(&mut self, vdm: VdmData) -> impl Future<Output = Result<(), NotificationError>> {
ready(
self.0
.try_send(PortEventData::Vdm(vdm))
.ok_or(NotificationError::WouldBlock),
)
}

fn notify_discover_mode_completed(&mut self) -> impl Future<Output = Result<(), NotificationError>> {
ready(
self.0
.try_send(PortEventData::DiscoverModeCompleted)
.ok_or(NotificationError::WouldBlock),
)
}

fn notify_usb_mux_error_recovery(&mut self) -> impl Future<Output = Result<(), NotificationError>> {
ready(
self.0
.try_send(PortEventData::UsbMuxErrorRecovery)
.ok_or(NotificationError::WouldBlock),
)
}

fn notify_dp_status_update(&mut self, status: DpStatus) -> impl Future<Output = Result<(), NotificationError>> {
ready(
self.0
.try_send(PortEventData::DpStatusUpdate(status))
.ok_or(NotificationError::WouldBlock),
)
}
}

impl<S: NonBlockingSender<PortEventData>> From<S> for NonBlockingSenderNotifier<S> {
fn from(sender: S) -> Self {
Self(sender)
}
}

/// New-type that implements the [`Notifier`] trait for any [`Sender<PortEventData>`].
///
/// This allows the user to choose blocking/non-blocking behavior when a type supports both.
pub struct SenderNotifier<S: Sender<PortEventData>>(pub S);

impl<S: Sender<PortEventData>> Notifier for SenderNotifier<S> {
async fn notify_status_changed(
&mut self,
status_event: PortStatusEventBitfield,
previous_status: PortStatus,
current_status: PortStatus,
) -> Result<(), NotificationError> {
self.0
.send(PortEventData::StatusChanged(StatusChangedData {
status_event,
previous_status,
current_status,
}))
.await;
Ok(())
}

async fn notify_alert(&mut self, alert: Ado) -> Result<(), NotificationError> {
self.0.send(PortEventData::Alert(alert)).await;
Ok(())
}

async fn notify_vdm(&mut self, vdm: VdmData) -> Result<(), NotificationError> {
self.0.send(PortEventData::Vdm(vdm)).await;
Ok(())
}

async fn notify_discover_mode_completed(&mut self) -> Result<(), NotificationError> {
self.0.send(PortEventData::DiscoverModeCompleted).await;
Ok(())
}

async fn notify_usb_mux_error_recovery(&mut self) -> Result<(), NotificationError> {
self.0.send(PortEventData::UsbMuxErrorRecovery).await;
Ok(())
}

async fn notify_dp_status_update(&mut self, status: DpStatus) -> Result<(), NotificationError> {
self.0.send(PortEventData::DpStatusUpdate(status)).await;
Ok(())
}
}

impl<S: Sender<PortEventData>> From<S> for SenderNotifier<S> {
fn from(sender: S) -> Self {
Self(sender)
}
}

#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
Expand Down
1 change: 1 addition & 0 deletions type-c-interface/src/port/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pub mod electrical_disconnect;
pub mod event;
pub mod max_sink_voltage;
pub mod notification;
pub mod pd;
pub mod power;
pub mod retimer;
Expand Down
80 changes: 80 additions & 0 deletions type-c-interface/src/port/notification.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//! Traits and types for port notifications.

use embedded_services::sync::Lockable;
use embedded_usb_pd::PdError;
use embedded_usb_pd::ado::Ado;

use crate::control::dp::DpStatus;
use crate::control::pd::PortStatus;
use crate::port::event::{PortStatusEventBitfield, VdmData};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub enum Error {
/// The requested operation would block
WouldBlock,
}

/// Port notifier trait
pub trait Notifier {
Comment on lines +19 to +20
/// Notify that a port's status has changed
fn notify_status_changed(
&mut self,
status_event: PortStatusEventBitfield,
previous_status: PortStatus,
current_status: PortStatus,
) -> impl Future<Output = Result<(), Error>>;
/// Notify that a PD alert was received
fn notify_alert(&mut self, alert: Ado) -> impl Future<Output = Result<(), Error>>;
/// Notify of a VDM event
fn notify_vdm(&mut self, vdm: VdmData) -> impl Future<Output = Result<(), Error>>;
/// Notify that discover mode has completed
fn notify_discover_mode_completed(&mut self) -> impl Future<Output = Result<(), Error>>;
/// Notify of a USB mux error recovery
fn notify_usb_mux_error_recovery(&mut self) -> impl Future<Output = Result<(), Error>>;
/// Notify of a DisplayPort status update
fn notify_dp_status_update(&mut self, status: DpStatus) -> impl Future<Output = Result<(), Error>>;
}

/// Port notification handler
pub trait NotificationHandler<'port> {
type Port: Lockable<Inner: crate::port::pd::Pd> + 'port;

/// Handle a notification that a port's status has changed
fn process_notify_status_changed(
&mut self,
port: &'port Self::Port,
status_event: PortStatusEventBitfield,
previous_status: PortStatus,
current_status: PortStatus,
) -> impl Future<Output = Result<(), PdError>>;
/// Handle a notification that a PD alert was received
fn process_notify_alert(
&mut self,
port: &'port Self::Port,
alert: Ado,
) -> impl Future<Output = Result<(), PdError>>;
/// Handle a notification of a VDM event
fn process_notify_vdm(
&mut self,
port: &'port Self::Port,
vdm: VdmData,
) -> impl Future<Output = Result<(), PdError>>;
/// Handle a notification that discover mode has completed
fn process_notify_discover_mode_completed(
&mut self,
port: &'port Self::Port,
) -> impl Future<Output = Result<(), PdError>>;
/// Handle a notification of a USB mux error recovery
fn process_notify_usb_mux_error_recovery(
&mut self,
port: &'port Self::Port,
) -> impl Future<Output = Result<(), PdError>>;
/// Handle a notification of a DisplayPort status update
fn process_notify_dp_status_update(
&mut self,
port: &'port Self::Port,
status: DpStatus,
) -> impl Future<Output = Result<(), PdError>>;
}
Loading
Loading