11//! Device struct and methods for component communication
22use core:: future:: Future ;
33
4+ #[ cfg( feature = "defmt" ) ]
5+ use defmt:: error;
6+
47use embassy_sync:: blocking_mutex:: raw:: NoopRawMutex ;
5- use embassy_sync:: channel:: Channel ;
68use embassy_sync:: mutex:: Mutex ;
79use embedded_cfu_protocol:: components:: { CfuComponentInfo , CfuComponentStorage , CfuComponentTraits } ;
810use embedded_cfu_protocol:: protocol_definitions:: * ;
@@ -12,6 +14,7 @@ use heapless::Vec;
1214use super :: CfuError ;
1315use crate :: cfu:: route_request;
1416use crate :: intrusive_list;
17+ use crate :: ipc:: deferred;
1518
1619/// Component internal update state
1720#[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
@@ -57,6 +60,16 @@ impl Default for InternalState {
5760 }
5861}
5962
63+ /// Request to the cfu service
64+ #[ derive( Debug , PartialEq ) ]
65+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
66+ pub struct Request {
67+ /// Component that sent this request
68+ pub id : ComponentId ,
69+ /// Request data
70+ pub data : RequestData ,
71+ }
72+
6073/// CFU Request types and necessary data
6174#[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
6275#[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
@@ -93,17 +106,16 @@ pub enum InternalResponseData {
93106 ComponentPrepared ,
94107}
95108
96- /// Channel size for device requests
97- pub const DEVICE_CHANNEL_SIZE : usize = 1 ;
109+ /// Wrapper type to make code cleaner
110+ pub type InternalResponse = Result < InternalResponseData , CfuError > ;
98111
99112/// CfuDevice struct
100113/// Can be inserted in an intrusive-list+
101114pub struct CfuDevice {
102115 node : intrusive_list:: Node ,
103116 component_id : ComponentId ,
104117 state : Mutex < NoopRawMutex , InternalState > ,
105- request : Channel < NoopRawMutex , RequestData , DEVICE_CHANNEL_SIZE > ,
106- response : Channel < NoopRawMutex , InternalResponseData , DEVICE_CHANNEL_SIZE > ,
118+ request : deferred:: Channel < NoopRawMutex , Request , InternalResponse > ,
107119}
108120
109121impl intrusive_list:: NodeContainer for CfuDevice {
@@ -124,15 +136,17 @@ impl CfuDeviceContainer for CfuDevice {
124136 }
125137}
126138
139+ /// Convenience type for CFU request
140+ pub type CfuRequest < ' a > = deferred:: Request < ' a , NoopRawMutex , Request , InternalResponse > ;
141+
127142impl CfuDevice {
128143 /// Constructor for CfuDevice
129144 pub fn new ( component_id : ComponentId ) -> Self {
130145 Self {
131146 node : intrusive_list:: Node :: uninit ( ) ,
132147 component_id,
133148 state : Mutex :: new ( InternalState :: default ( ) ) ,
134- request : Channel :: new ( ) ,
135- response : Channel :: new ( ) ,
149+ request : deferred:: Channel :: new ( ) ,
136150 }
137151 }
138152 /// Getter for component id
@@ -145,30 +159,34 @@ impl CfuDevice {
145159 * self . state . lock ( ) . await
146160 }
147161
148- /// Send a request to this device
149- pub async fn send_request ( & self , request : RequestData ) {
150- self . request . send ( request) . await ;
151- }
152-
153162 /// Sends a request to this device and returns a response
154- pub async fn execute_device_request ( & self , request : RequestData ) -> Result < InternalResponseData , CfuProtocolError > {
155- self . send_request ( request) . await ;
156- Ok ( self . wait_response ( ) . await )
163+ pub async fn execute_device_request ( & self , request : Request ) -> InternalResponse {
164+ self . request . execute ( request) . await
157165 }
158166
159- /// Wait for a request
160- pub async fn wait_request ( & self ) -> RequestData {
167+ /// Send a response
168+ pub async fn receive ( & self ) -> CfuRequest {
161169 self . request . receive ( ) . await
162170 }
163171
164- /// Send a response
165- pub async fn send_response ( & self , response : InternalResponseData ) {
166- self . response . send ( response) . await ;
172+ /// Send a request to the device, returns a request ID for later tracking if needed
173+ pub async fn send_request ( & self , request : Request ) -> deferred:: RequestId {
174+ self . request . send_command ( request) . await
175+ }
176+
177+ /// Wait for a response for a specific request ID
178+ pub async fn wait_response ( & self , id : deferred:: RequestId ) -> InternalResponse {
179+ self . request . wait_for_response ( id) . await
167180 }
168181
169- /// Waits for a response
170- pub async fn wait_response ( & self ) -> InternalResponseData {
171- self . response . receive ( ) . await
182+ /// Wait for the next response, regardless of request ID
183+ pub async fn wait_any_response ( & self ) -> InternalResponse {
184+ self . request . wait_for_next_response ( ) . await
185+ }
186+
187+ /// Send a response
188+ pub async fn send_response ( & self , id : deferred:: RequestId , response : InternalResponse ) {
189+ self . request . send_response ( response, id) . await
172190 }
173191}
174192
@@ -213,7 +231,8 @@ impl<W: CfuWriter> CfuComponentDefault<W> {
213231 }
214232 /// wait for a request and process it
215233 pub async fn process_request ( & self ) -> Result < ( ) , CfuError > {
216- match self . device . wait_request ( ) . await {
234+ let request = self . device . receive ( ) . await ;
235+ match request. command . data {
217236 RequestData :: FwVersionRequest => {
218237 let fwv = self . get_fw_version ( ) . await . map_err ( CfuError :: ProtocolError ) ?;
219238 let dev_inf = FwVerComponentInfo :: new ( fwv, self . get_component_id ( ) ) ;
@@ -250,9 +269,7 @@ impl<W: CfuWriter> CfuComponentDefault<W> {
250269 ) ,
251270 component_info : comp_info,
252271 } ;
253- self . device
254- . send_response ( InternalResponseData :: FwVersionResponse ( resp) )
255- . await ;
272+ request. respond ( Ok ( InternalResponseData :: FwVersionResponse ( resp) ) ) ;
256273 }
257274 RequestData :: PrepareComponentForUpdate => {
258275 self . storage_prepare ( )
@@ -263,9 +280,7 @@ impl<W: CfuWriter> CfuComponentDefault<W> {
263280 // accept any and all offers regardless of what version it is
264281 if buf. component_info . component_id == self . get_component_id ( ) {
265282 let resp = FwUpdateOfferResponse :: new_accept ( HostToken :: Driver ) ;
266- self . device
267- . send_response ( InternalResponseData :: OfferResponse ( resp) )
268- . await ;
283+ request. respond ( Ok ( InternalResponseData :: OfferResponse ( resp) ) ) ;
269284 }
270285 }
271286 RequestData :: GiveContent ( buf) => {
@@ -276,8 +291,14 @@ impl<W: CfuWriter> CfuComponentDefault<W> {
276291 . cfu_write ( Some ( offset) , & buf. data )
277292 . await
278293 . map_err ( |e| CfuError :: ProtocolError ( CfuProtocolError :: WriterError ( e) ) ) ?;
294+ request. respond ( Ok ( InternalResponseData :: ContentResponse ( FwUpdateContentResponse :: new (
295+ buf. header . sequence_num ,
296+ CfuUpdateContentResponseStatus :: Success ,
297+ ) ) ) ) ;
298+ }
299+ RequestData :: FinalizeUpdate => {
300+ request. respond ( Ok ( InternalResponseData :: ComponentPrepared ) ) ;
279301 }
280- RequestData :: FinalizeUpdate => { }
281302 }
282303 Ok ( ( ) )
283304 }
0 commit comments