Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Transport Service Definitions
//! Comms Service Definitions

use core::any::{Any, TypeId};
use core::cell::Cell;
Expand Down Expand Up @@ -57,7 +57,7 @@ pub enum Internal {
Oem(OemKey),
}

/// External identifier for transport routing
/// External identifier for routing
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum External {
Expand All @@ -71,26 +71,26 @@ pub enum External {
Oem(OemKey),
}

/// Endpoint identifier for transport routing
/// Endpoint identifier for routing
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Endpoint {
pub enum EndpointID {
/// route to/from an internal source
Internal(Internal),

/// route to/from an external source
External(External),
}

impl From<Internal> for Endpoint {
impl From<Internal> for EndpointID {
fn from(value: Internal) -> Self {
Endpoint::Internal(value)
EndpointID::Internal(value)
}
}

impl From<External> for Endpoint {
impl From<External> for EndpointID {
fn from(value: External) -> Self {
Endpoint::External(value)
EndpointID::External(value)
}
}

Expand Down Expand Up @@ -136,77 +136,77 @@ impl<'a> Data<'a> {
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Message<'a> {
/// where this message came from
pub from: Endpoint,
pub from: EndpointID,

/// where this message is going
pub to: Endpoint,
pub to: EndpointID,

/// message content
pub data: Data<'a>,
}

/// Receive trait for Registration implementers
pub trait MessageDelegate {
/// Trait to receive messages
pub trait MailboxDelegate {
/// Receive a Message (typically, push contents to queue or queue some action)
fn process(&self, message: &Message);
fn receive(&self, message: &Message);
}

/// Primary node registration for receiving messages from the transport service
pub struct EndpointLink {
/// Primary node registration for receiving messages from the comms service
pub struct Endpoint {
node: Node,
who: Endpoint,
delegator: Cell<Option<&'static dyn MessageDelegate>>,
id: EndpointID,
delegator: Cell<Option<&'static dyn MailboxDelegate>>,
}

impl NodeContainer for EndpointLink {
impl NodeContainer for Endpoint {
fn get_node(&self) -> &Node {
&self.node
}
}

impl EndpointLink {
impl Endpoint {
/// Get endpoint ID
pub fn get_id(&self) -> EndpointID {
self.id
}

/// use this when static initialization occurs, internal fields will be validated in register_subscriber() later
pub const fn uninit(who_am_i: Endpoint) -> Self {
pub const fn uninit(id: EndpointID) -> Self {
Self {
node: Node::uninit(),
who: who_am_i,
id: id,
delegator: Cell::new(None),
}
}

/// Send a generic message to a Target
pub async fn send(&self, to: Endpoint, data: &impl Any) -> Result<(), Infallible> {
route(Message {
from: self.who,
to,
data: Data::new(data),
})
.await
/// Send a generic message to an endpoint
pub async fn send(&self, to: EndpointID, data: &impl Any) -> Result<(), Infallible> {
send(self.id, to, data).await
}

fn init(&self, rx: &'static dyn MessageDelegate) {
fn init(&self, rx: &'static dyn MailboxDelegate) {
self.delegator.set(Some(rx));
}

fn process(&self, message: &Message) {
if let Some(delegator) = self.delegator.get() {
delegator.process(message);
delegator.receive(message);
}
}
}

/// initialize receiver/transport node for message handling
/// initialize receiver node for message handling
pub async fn register_endpoint(
this: &'static impl MessageDelegate,
node: &'static EndpointLink,
this: &'static impl MailboxDelegate,
node: &'static Endpoint,
) -> Result<(), intrusive_list::Error> {
node.init(this);
get_list(node.who).get().await.push(node)
get_list(node.id).get().await.push(node)
}

fn get_list(target: Endpoint) -> &'static OnceLock<IntrusiveList> {
fn get_list(target: EndpointID) -> &'static OnceLock<IntrusiveList> {
match target {
Endpoint::External(ext_endpoint) => match ext_endpoint {
EndpointID::External(ext_endpoint) => match ext_endpoint {
External::Host => {
static EXTERNAL_HOST: OnceLock<IntrusiveList> = OnceLock::new();
&EXTERNAL_HOST
Expand All @@ -220,7 +220,7 @@ fn get_list(target: Endpoint) -> &'static OnceLock<IntrusiveList> {
&EXTERNAL_OEM
}
},
Endpoint::Internal(int_endpoint) => {
EndpointID::Internal(int_endpoint) => {
use Internal::*;

static INTERNAL_LIST_PLATFORM_INFO: OnceLock<IntrusiveList> = OnceLock::new();
Expand Down Expand Up @@ -256,13 +256,23 @@ fn get_list(target: Endpoint) -> &'static OnceLock<IntrusiveList> {
}
}

/// Send a generic message to an endpoint
pub async fn send(from: EndpointID, to: EndpointID, data: &impl Any) -> Result<(), Infallible> {
route(Message {
from: from,
to,
data: Data::new(data),
})
.await
}

/// route a message to any valid receiver nodes
pub async fn route(message: Message<'_>) -> Result<(), Infallible> {
async fn route(message: Message<'_>) -> Result<(), Infallible> {
let list = get_list(message.to).get().await;

for rxq in list {
if let Some(endpoint) = rxq.data::<EndpointLink>() {
if message.to == endpoint.who {
if let Some(endpoint) = rxq.data::<Endpoint>() {
if message.to == endpoint.id {
endpoint.process(&message);
}
}
Expand Down
18 changes: 9 additions & 9 deletions embedded-service/src/hid/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use embassy_sync::once_lock::OnceLock;
use embassy_sync::signal::Signal;

use crate::buffer::SharedRef;
use crate::transport::{self, Endpoint, EndpointLink, External, Internal, MessageDelegate};
use crate::comms::{self, Endpoint, EndpointID, External, Internal, MailboxDelegate};
use crate::{error, intrusive_list, IntrusiveList, Node, NodeContainer};

mod command;
Expand Down Expand Up @@ -156,7 +156,7 @@ impl Default for RegisterFile {
/// HID device that responds to HID requests
pub struct Device {
node: Node,
tp: EndpointLink,
tp: Endpoint,
request: Signal<NoopRawMutex, Request<'static>>,
/// Device ID
pub id: DeviceId,
Expand All @@ -181,7 +181,7 @@ impl Device {
pub fn new(id: DeviceId, regs: RegisterFile) -> Self {
Self {
node: Node::uninit(),
tp: EndpointLink::uninit(Endpoint::Internal(Internal::Hid)),
tp: Endpoint::uninit(EndpointID::Internal(Internal::Hid)),
request: Signal::new(),
id,
regs,
Expand All @@ -199,7 +199,7 @@ impl Device {
id: self.id,
data: MessageData::Response(response),
};
self.tp.send(Endpoint::External(External::Host), &message).await
self.tp.send(EndpointID::External(External::Host), &message).await
}
}

Expand All @@ -209,8 +209,8 @@ impl DeviceContainer for Device {
}
}

impl MessageDelegate for Device {
fn process(&self, message: &transport::Message) {
impl MailboxDelegate for Device {
fn receive(&self, message: &comms::Message) {
if let Some(message) = message.data.get::<Message>() {
if message.id != self.id {
return;
Expand Down Expand Up @@ -304,7 +304,7 @@ pub fn init() {
pub async fn register_device(device: &'static impl DeviceContainer) -> Result<(), intrusive_list::Error> {
let device = device.get_hid_device();
CONTEXT.get().await.devices.push(device)?;
transport::register_endpoint(device, &device.tp).await
comms::register_endpoint(device, &device.tp).await
}

/// Find a device by its ID
Expand All @@ -323,12 +323,12 @@ pub async fn get_device(id: DeviceId) -> Option<&'static Device> {
}

/// Convenience function to send a request to a HID device
pub async fn send_request(tp: &EndpointLink, to: DeviceId, request: Request<'static>) -> Result<(), Infallible> {
pub async fn send_request(tp: &Endpoint, to: DeviceId, request: Request<'static>) -> Result<(), Infallible> {
let message = Message {
id: to,
data: MessageData::Request(request),
};
tp.send(Endpoint::Internal(Internal::Hid), &message).await
tp.send(EndpointID::Internal(Internal::Hid), &message).await
}

#[cfg(test)]
Expand Down
4 changes: 2 additions & 2 deletions embedded-service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ pub use intrusive_list::*;
/// short-hand include all pre-baked services
pub mod activity;
pub mod buffer;
pub mod comms;
pub mod fmt;
pub mod hid;
pub mod transport;

/// initialize all service static interfaces as required. Ideally, this is done before subsystem initialization
pub async fn init() {
transport::init();
comms::init();
activity::init();
hid::init();
}
28 changes: 14 additions & 14 deletions examples/rt685s-evk/src/bin/mock_espi_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ mod espi_service {
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
use embassy_sync::once_lock::OnceLock;
use embassy_sync::signal::Signal;
use embedded_services::transport::{self, Endpoint, External, Internal};
use embedded_services::comms::{self, EndpointID, External, Internal};

struct Service {
endpoint: transport::EndpointLink,
endpoint: comms::Endpoint,

// This is can be an Embassy signal or channel or whatever Embassy async notification construct
signal: Signal<NoopRawMutex, TxMessage>,
Expand All @@ -36,14 +36,14 @@ mod espi_service {
impl Service {
fn new() -> Self {
Service {
endpoint: transport::EndpointLink::uninit(Endpoint::External(External::Host)),
endpoint: comms::Endpoint::uninit(EndpointID::External(External::Host)),
signal: Signal::new(),
}
}
}

impl transport::MessageDelegate for Service {
fn process(&self, message: &transport::Message) {
impl comms::MailboxDelegate for Service {
fn receive(&self, message: &comms::Message) {
if let Some(msg) = message.data.get::<TxMessage>() {
self.signal.signal(*msg);
}
Expand All @@ -56,7 +56,7 @@ mod espi_service {
pub async fn init() {
let espi_service = ESPI_SERVICE.get_or_init(|| Service::new());

transport::register_endpoint(espi_service, &espi_service.endpoint)
comms::register_endpoint(espi_service, &espi_service.endpoint)
.await
.unwrap();
}
Expand All @@ -68,7 +68,7 @@ mod espi_service {
espi_service
.endpoint
.send(
Endpoint::Internal(Internal::Battery),
EndpointID::Internal(Internal::Battery),
&RxMessage::SetBatteryCharge(battery_charge),
)
.await
Expand Down Expand Up @@ -99,10 +99,10 @@ mod battery_service {
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
use embassy_sync::once_lock::OnceLock;
use embassy_sync::signal::Signal;
use embedded_services::transport::{self, Endpoint, External, Internal};
use embedded_services::comms::{self, EndpointID, External, Internal};

struct Service {
endpoint: transport::EndpointLink,
endpoint: comms::Endpoint,

// This is can be an Embassy signal or channel or whatever Embassy async notification construct
signal: Signal<NoopRawMutex, RxMessage>,
Expand All @@ -111,14 +111,14 @@ mod battery_service {
impl Service {
fn new() -> Self {
Service {
endpoint: transport::EndpointLink::uninit(Endpoint::Internal(Internal::Battery)),
endpoint: comms::Endpoint::uninit(EndpointID::Internal(Internal::Battery)),
signal: Signal::new(),
}
}
}

impl transport::MessageDelegate for Service {
fn process(&self, message: &transport::Message) {
impl comms::MailboxDelegate for Service {
fn receive(&self, message: &comms::Message) {
if let Some(msg) = message.data.get::<RxMessage>() {
self.signal.signal(*msg);
}
Expand All @@ -131,7 +131,7 @@ mod battery_service {
pub async fn init() {
let battery_service = BATTERY_SERVICE.get_or_init(|| Service::new());

transport::register_endpoint(battery_service, &battery_service.endpoint)
comms::register_endpoint(battery_service, &battery_service.endpoint)
.await
.unwrap();
}
Expand All @@ -146,7 +146,7 @@ mod battery_service {
battery_service
.endpoint
.send(
Endpoint::External(External::Host),
EndpointID::External(External::Host),
&TxMessage::UpdateBatteryStatus(battery_status),
)
.await
Expand Down
Loading
Loading