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
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.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ embassy-sync = { git = "https://github.com/embassy-rs/embassy" }
embassy-time = { git = "https://github.com/embassy-rs/embassy" }
embassy-time-driver = { git = "https://github.com/embassy-rs/embassy" }
embedded-batteries-async = "0.1.0"
embedded-cfu-protocol = { git = "https://github.com/OpenDevicePartnership/embedded-cfu", version = "0.1.0" }
embedded-cfu-protocol = { git = "https://github.com/OpenDevicePartnership/embedded-cfu" }
embedded-hal = "1.0"
embedded-hal-async = "1.0"
embedded-hal-nb = "1.0"
Expand Down
34 changes: 16 additions & 18 deletions battery-service/src/device.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use core::cell::Cell;

use embassy_sync::channel::Channel;
use embassy_sync::{channel::Channel, mutex::Mutex};
use embassy_time::Duration;
use embedded_services::{GlobalRawMutex, Node, NodeContainer};
use embedded_services::{GlobalRawMutex, Node, NodeContainer, SyncCell};

#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
Expand Down Expand Up @@ -116,9 +114,9 @@ pub struct Device {
id: DeviceId,
command: Channel<GlobalRawMutex, Command, 1>,
response: Channel<GlobalRawMutex, Response, 1>,
dynamic_battery_cache: Cell<DynamicBatteryMsgs>,
static_battery_cache: Cell<StaticBatteryMsgs>,
timeout: Cell<Duration>,
dynamic_battery_cache: Mutex<GlobalRawMutex, DynamicBatteryMsgs>,
static_battery_cache: Mutex<GlobalRawMutex, StaticBatteryMsgs>,
timeout: SyncCell<Duration>,
}

impl Device {
Expand All @@ -128,9 +126,9 @@ impl Device {
id,
command: Channel::new(),
response: Channel::new(),
dynamic_battery_cache: Cell::default(),
static_battery_cache: Cell::default(),
timeout: Cell::new(Duration::from_secs(60)),
dynamic_battery_cache: Mutex::default(),
static_battery_cache: Mutex::default(),
timeout: SyncCell::new(Duration::from_secs(60)),
}
}

Expand Down Expand Up @@ -166,23 +164,23 @@ impl Device {
}

/// Set dynamic battery cache with updated values.
pub fn set_dynamic_battery_cache(&self, new_values: DynamicBatteryMsgs) {
self.dynamic_battery_cache.set(new_values);
pub async fn set_dynamic_battery_cache(&self, new_values: DynamicBatteryMsgs) {
*self.dynamic_battery_cache.lock().await = new_values;
}

/// Set static battery cache with updated values.
pub fn set_static_battery_cache(&self, new_values: StaticBatteryMsgs) {
self.static_battery_cache.set(new_values);
pub async fn set_static_battery_cache(&self, new_values: StaticBatteryMsgs) {
*self.static_battery_cache.lock().await = new_values;
}

/// Get dynamic battery cache.
pub fn get_dynamic_battery_cache(&self) -> DynamicBatteryMsgs {
self.dynamic_battery_cache.get()
pub async fn get_dynamic_battery_cache(&self) -> DynamicBatteryMsgs {
*self.dynamic_battery_cache.lock().await
}

/// Get static battery cache.
pub fn get_static_battery_cache(&self) -> StaticBatteryMsgs {
self.static_battery_cache.get()
pub async fn get_static_battery_cache(&self) -> StaticBatteryMsgs {
*self.static_battery_cache.lock().await
}

/// Set device timeout.
Expand Down
4 changes: 2 additions & 2 deletions battery-service/src/wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ impl<'a, C: Controller> Wrapper<'a, C> {
},
Command::UpdateStaticCache => match controller.get_static_data().await {
Ok(static_data) => {
device.set_static_battery_cache(static_data);
device.set_static_battery_cache(static_data).await;
device
.send_response(Ok(crate::device::InternalResponse::Complete))
.await;
Expand All @@ -88,7 +88,7 @@ impl<'a, C: Controller> Wrapper<'a, C> {
},
Command::UpdateDynamicCache => match controller.get_dynamic_data().await {
Ok(dynamic_data) => {
device.set_dynamic_battery_cache(dynamic_data);
device.set_dynamic_battery_cache(dynamic_data).await;
device
.send_response(Ok(crate::device::InternalResponse::Complete))
.await;
Expand Down
14 changes: 7 additions & 7 deletions cfu-service/src/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use core::future::pending;

use embassy_futures::select::{Either3, select3};
use embassy_sync::{
channel::{DynamicReceiver, DynamicSender},
channel::{SendDynamicReceiver, SendDynamicSender},
mutex::Mutex,
};
use embassy_time::{Duration, TimeoutError, with_timeout};
Expand Down Expand Up @@ -57,10 +57,10 @@ pub struct Buffer<'a> {
state: Mutex<GlobalRawMutex, State>,
/// Component ID to buffer requests for
buffered_id: ComponentId,
/// Sender for the buffer
buffer_sender: DynamicSender<'a, FwUpdateContentCommand>,
/// Receiver for the buffer
buffer_receiver: DynamicReceiver<'a, FwUpdateContentCommand>,
/// Sender for the buffer. Must be used with a channel with an underlying Mutex that is Send and Sync.
buffer_sender: SendDynamicSender<'a, FwUpdateContentCommand>,
/// Receiver for the buffer. Must be used with a channel with an underlying Mutex that is Send and Sync.
buffer_receiver: SendDynamicReceiver<'a, FwUpdateContentCommand>,
/// Configuration for the buffer
config: Config,
}
Expand All @@ -81,8 +81,8 @@ impl<'a> Buffer<'a> {
pub fn new(
external_id: ComponentId,
buffered_id: ComponentId,
buffer_sender: DynamicSender<'a, FwUpdateContentCommand>,
buffer_receiver: DynamicReceiver<'a, FwUpdateContentCommand>,
buffer_sender: SendDynamicSender<'a, FwUpdateContentCommand>,
buffer_receiver: SendDynamicReceiver<'a, FwUpdateContentCommand>,
config: Config,
) -> Self {
Self {
Expand Down
49 changes: 22 additions & 27 deletions cfu-service/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,39 @@ use core::future::Future;
use embedded_cfu_protocol::components::CfuComponentTraits;
use embedded_cfu_protocol::host::{CfuHostStates, CfuUpdater};
use embedded_cfu_protocol::protocol_definitions::*;
use embedded_cfu_protocol::{CfuImage, CfuWriter, CfuWriterDefault, CfuWriterError};
use embedded_cfu_protocol::{
CfuImage,
writer::{CfuWriterAsync, CfuWriterError, CfuWriterNop},
};
use heapless::Vec;

use crate::CfuError;

/// All host side Cfu traits, in some cases this will originate from a OS driver for CFU
pub trait CfuHost: CfuHostStates {
pub trait CfuHost<W>: CfuHostStates<W> {
/// Get all images
fn get_cfu_images<I: CfuImage>(&self) -> impl Future<Output = Result<Vec<I, MAX_CMPT_COUNT>, CfuError>>;
/// Gets the firmware version of all components
fn get_all_fw_versions<T: CfuWriter>(
fn get_all_fw_versions(
self,
writer: &mut T,
writer: &mut W,
primary_cmpt: ComponentId,
) -> impl Future<Output = Result<GetFwVersionResponse, CfuError>>;
/// Goes through the offer list and returns a slice of offer responses
fn process_cfu_offers<'a, T: CfuWriter>(
fn process_cfu_offers<'a>(
offer_commands: &'a [FwUpdateOffer],
writer: &mut T,
writer: &mut W,
) -> impl Future<Output = Result<&'a [FwUpdateOfferResponse], CfuError>>;
/// For a specific component, update its content
fn update_cfu_content<T: CfuWriter>(
writer: &mut T,
) -> impl Future<Output = Result<FwUpdateContentResponse, CfuError>>;
fn update_cfu_content(writer: &mut W) -> impl Future<Output = Result<FwUpdateContentResponse, CfuError>>;
/// For a specific image that was updated, validate its content
fn is_cfu_image_valid<I: CfuImage>(image: I) -> impl Future<Output = Result<bool, CfuError>>;
}

pub struct CfuHostInstance<I: CfuImage, C: CfuComponentTraits> {
pub updater: CfuUpdater,
pub images: heapless::Vec<I, MAX_CMPT_COUNT>,
pub writer: CfuWriterDefault,
pub writer: CfuWriterNop,
pub primary_cmpt: C,
pub host_token: HostToken,
}
Expand All @@ -45,15 +46,15 @@ impl<I: CfuImage, C: CfuComponentTraits> CfuHostInstance<I, C> {
Self {
updater: CfuUpdater {},
images: Vec::new(),
writer: CfuWriterDefault::default(),
writer: CfuWriterNop,
primary_cmpt,
host_token: HostToken::Driver,
}
}
}

impl<I: CfuImage, C: CfuComponentTraits> CfuHostStates for CfuHostInstance<I, C> {
async fn start_transaction<T: CfuWriter>(self, _writer: &mut T) -> Result<FwUpdateOfferResponse, CfuProtocolError> {
impl<I: CfuImage, C: CfuComponentTraits, W: CfuWriterAsync> CfuHostStates<W> for CfuHostInstance<I, C> {
async fn start_transaction(self, _writer: &mut W) -> Result<FwUpdateOfferResponse, CfuProtocolError> {
let _mock_cmd = FwUpdateOfferInformation::new(OfferInformationComponentInfo::new(
HostToken::Driver,
SpecialComponentIds::Info,
Expand All @@ -62,10 +63,7 @@ impl<I: CfuImage, C: CfuComponentTraits> CfuHostStates for CfuHostInstance<I, C>
let mockresponse = FwUpdateOfferResponse::default();
Ok(mockresponse)
}
async fn notify_start_offer_list<T: CfuWriter>(
self,
writer: &mut T,
) -> Result<FwUpdateOfferResponse, CfuProtocolError> {
async fn notify_start_offer_list(self, writer: &mut W) -> Result<FwUpdateOfferResponse, CfuProtocolError> {
// Serialize FwUpdateOfferInformation to bytes
let mock_cmd = FwUpdateOfferInformation::new(OfferInformationComponentInfo::new(
HostToken::Driver,
Expand All @@ -89,10 +87,7 @@ impl<I: CfuImage, C: CfuComponentTraits> CfuHostStates for CfuHostInstance<I, C>
}
}

async fn notify_end_offer_list<T: CfuWriter>(
self,
writer: &mut T,
) -> Result<FwUpdateOfferResponse, CfuProtocolError> {
async fn notify_end_offer_list(self, writer: &mut W) -> Result<FwUpdateOfferResponse, CfuProtocolError> {
let mock_cmd = FwUpdateOfferInformation::new(OfferInformationComponentInfo::new(
HostToken::Driver,
SpecialComponentIds::Info,
Expand Down Expand Up @@ -128,14 +123,14 @@ impl<I: CfuImage, C: CfuComponentTraits> CfuHostStates for CfuHostInstance<I, C>
}
}

impl<I: CfuImage, C: CfuComponentTraits> CfuHost for CfuHostInstance<I, C> {
impl<I: CfuImage, C: CfuComponentTraits, W: CfuWriterAsync> CfuHost<W> for CfuHostInstance<I, C> {
async fn get_cfu_images<T: CfuImage>(&self) -> Result<Vec<T, MAX_CMPT_COUNT>, CfuError> {
Err(CfuError::BadImage)
}

async fn get_all_fw_versions<T: CfuWriter>(
async fn get_all_fw_versions(
self,
_writer: &mut T,
_writer: &mut W,
primary_cmpt: ComponentId,
) -> Result<GetFwVersionResponse, CfuError> {
let mut component_count: u8 = 0;
Expand Down Expand Up @@ -172,15 +167,15 @@ impl<I: CfuImage, C: CfuComponentTraits> CfuHost for CfuHostInstance<I, C> {
}
}

async fn process_cfu_offers<'a, T: CfuWriter>(
async fn process_cfu_offers<'a>(
_offer_commands: &'a [FwUpdateOffer],
_writer: &mut T,
_writer: &mut W,
) -> Result<&'a [FwUpdateOfferResponse], CfuError> {
// TODO
Err(CfuError::BadImage)
}

async fn update_cfu_content<T: CfuWriter>(_writer: &mut T) -> Result<FwUpdateContentResponse, CfuError> {
async fn update_cfu_content(_writer: &mut W) -> Result<FwUpdateContentResponse, CfuError> {
Err(CfuError::ProtocolError(CfuProtocolError::WriterError(
CfuWriterError::Other,
)))
Expand Down
21 changes: 18 additions & 3 deletions cfu-service/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
#![no_std]

use embassy_sync::once_lock::OnceLock;
use embedded_cfu_protocol::client::CfuReceiveContent;
use embedded_cfu_protocol::components::CfuComponentTraits;
use embedded_cfu_protocol::protocol_definitions::*;
use embedded_services::cfu::component::*;
use embedded_services::cfu::{CfuError, ContextToken};
use embedded_services::{comms, error, info};
use embedded_services::{comms, error, info, trace};

pub mod buffer;
pub mod host;
Expand All @@ -17,8 +19,21 @@ pub struct CfuClient {
tp: comms::Endpoint,
}

/// use default "do-nothing" implementations
impl<T, C, E: Default> CfuReceiveContent<T, C, E> for CfuClient {}
impl<T, C> CfuReceiveContent<T, C, ()> for CfuClient {
async fn process_command(&self, _args: Option<T>, _cmd: C) -> Result<(), ()> {
trace!("CfuClient CfuReceiveContent::process_command do nothing implementation.");
Ok(())
}

async fn prepare_components(
&self,
_args: Option<T>,
_primary_component: impl CfuComponentTraits,
) -> Result<(), ()> {
trace!("CfuClient CfuReceiveContent::prepare_components do nothing implementation.");
Ok(())
}
}

impl CfuClient {
/// Create a new Cfu Client
Expand Down
Loading