11//! Policy state machine
2+ use embassy_time:: { with_timeout, Duration } ;
3+
24use super :: * ;
35use crate :: power:: policy:: { device, Error , PowerCapability } ;
46use crate :: { error, info} ;
57
8+ /// Default timeout for device commands to prevent the policy from getting stuck
9+ const DEFAULT_TIMEOUT : Duration = Duration :: from_millis ( 5000 ) ;
10+
611/// Policy state machine control
712pub struct Policy < ' a , S : Kind > {
813 device : & ' a device:: Device ,
@@ -42,23 +47,32 @@ impl<'a, S: Kind> Policy<'a, S> {
4247 }
4348 }
4449
45- async fn disconnect_internal ( & self ) -> Result < ( ) , Error > {
50+ /// Common disconnect function used by multiple states
51+ async fn disconnect_internal_no_timeout ( & self ) -> Result < ( ) , Error > {
4652 info ! ( "Device {} got disconnect request" , self . device. id( ) . 0 ) ;
4753 self . device
48- . execute_device_request ( device:: RequestData :: Disconnect )
54+ . execute_device_command ( device:: CommandData :: Disconnect )
4955 . await ?
5056 . complete_or_err ( ) ?;
5157 self . device . set_state ( device:: State :: Idle ) . await ;
5258 self . device . exit_recovery ( ) . await ;
5359 Ok ( ( ) )
5460 }
5561
56- /// Connect this device as a provider
57- async fn connect_provider_internal ( & self , capability : PowerCapability ) -> Result < ( ) , Error > {
62+ /// Common disconnect function used by multiple states
63+ async fn disconnect_internal ( & self ) -> Result < ( ) , Error > {
64+ match with_timeout ( DEFAULT_TIMEOUT , self . disconnect_internal_no_timeout ( ) ) . await {
65+ Ok ( r) => r,
66+ Err ( _) => Err ( Error :: Timeout ) ,
67+ }
68+ }
69+
70+ /// Common connect provider function used by multiple states
71+ async fn connect_provider_internal_no_timeout ( & self , capability : PowerCapability ) -> Result < ( ) , Error > {
5872 info ! ( "Device {} connecting provider" , self . device. id( ) . 0 ) ;
5973
6074 self . device
61- . execute_device_request ( device:: RequestData :: ConnectProvider ( capability) )
75+ . execute_device_command ( device:: CommandData :: ConnectProvider ( capability) )
6276 . await ?
6377 . complete_or_err ( ) ?;
6478
@@ -68,18 +82,29 @@ impl<'a, S: Kind> Policy<'a, S> {
6882
6983 Ok ( ( ) )
7084 }
85+
86+ /// Common connect provider function used by multiple states
87+ async fn connect_provider_internal ( & self , capability : PowerCapability ) -> Result < ( ) , Error > {
88+ match with_timeout ( DEFAULT_TIMEOUT , self . connect_provider_internal_no_timeout ( capability) ) . await {
89+ Ok ( r) => r,
90+ Err ( _) => Err ( Error :: Timeout ) ,
91+ }
92+ }
7193}
7294
7395// The policy can do nothing when no device is attached
7496impl Policy < ' _ , Detached > { }
7597
7698impl < ' a > Policy < ' a , Idle > {
7799 /// Connect this device as a consumer
78- pub async fn connect_consumer ( self , capability : PowerCapability ) -> Result < Policy < ' a , ConnectedConsumer > , Error > {
100+ pub async fn connect_consumer_no_timeout (
101+ self ,
102+ capability : PowerCapability ,
103+ ) -> Result < Policy < ' a , ConnectedConsumer > , Error > {
79104 info ! ( "Device {} connecting consumer" , self . device. id( ) . 0 ) ;
80105
81106 self . device
82- . execute_device_request ( device:: RequestData :: ConnectConsumer ( capability) )
107+ . execute_device_command ( device:: CommandData :: ConnectConsumer ( capability) )
83108 . await ?
84109 . complete_or_err ( ) ?;
85110
@@ -89,6 +114,23 @@ impl<'a> Policy<'a, Idle> {
89114 Ok ( Policy :: new ( self . device ) )
90115 }
91116
117+ /// Connect this device as a consumer
118+ pub async fn connect_consumer ( self , capability : PowerCapability ) -> Result < Policy < ' a , ConnectedConsumer > , Error > {
119+ match with_timeout ( DEFAULT_TIMEOUT , self . connect_consumer_no_timeout ( capability) ) . await {
120+ Ok ( r) => r,
121+ Err ( _) => Err ( Error :: Timeout ) ,
122+ }
123+ }
124+
125+ /// Connect this device as a provider
126+ pub async fn connect_provider_no_timeout (
127+ self ,
128+ capability : PowerCapability ,
129+ ) -> Result < Policy < ' a , ConnectedProvider > , Error > {
130+ self . connect_provider_internal_no_timeout ( capability) . await ?;
131+ Ok ( Policy :: new ( self . device ) )
132+ }
133+
92134 /// Connect this device as a provider
93135 pub async fn connect_provider ( self , capability : PowerCapability ) -> Result < Policy < ' a , ConnectedProvider > , Error > {
94136 self . connect_provider_internal ( capability) . await ?;
@@ -97,6 +139,12 @@ impl<'a> Policy<'a, Idle> {
97139}
98140
99141impl < ' a > Policy < ' a , ConnectedConsumer > {
142+ /// Disconnect this device
143+ pub async fn disconnect_no_timeout ( self ) -> Result < Policy < ' a , Idle > , Error > {
144+ self . disconnect_internal_no_timeout ( ) . await ?;
145+ Ok ( Policy :: new ( self . device ) )
146+ }
147+
100148 /// Disconnect this device
101149 pub async fn disconnect ( self ) -> Result < Policy < ' a , Idle > , Error > {
102150 self . disconnect_internal ( ) . await ?;
@@ -106,18 +154,36 @@ impl<'a> Policy<'a, ConnectedConsumer> {
106154
107155impl < ' a > Policy < ' a , ConnectedProvider > {
108156 /// Disconnect this device
109- pub async fn disconnect ( self ) -> Result < Policy < ' a , Idle > , Error > {
110- if let Err ( e) = self . disconnect_internal ( ) . await {
157+ pub async fn disconnect_no_timeout ( self ) -> Result < Policy < ' a , Idle > , Error > {
158+ if let Err ( e) = self . disconnect_internal_no_timeout ( ) . await {
111159 error ! ( "Error disconnecting device {}: {:?}" , self . device. id( ) . 0 , e) ;
112160 self . device . enter_recovery ( ) . await ;
113161 return Err ( e) ;
114162 }
115163 Ok ( Policy :: new ( self . device ) )
116164 }
117165
166+ /// Disconnect this device
167+ pub async fn disconnect ( self ) -> Result < Policy < ' a , Idle > , Error > {
168+ match with_timeout ( DEFAULT_TIMEOUT , self . disconnect_no_timeout ( ) ) . await {
169+ Ok ( r) => r,
170+ Err ( _) => Err ( Error :: Timeout ) ,
171+ }
172+ }
173+
118174 /// Connect this device as a provider
119- pub async fn connect_provider ( & self , capability : PowerCapability ) -> Result < ( ) , Error > {
120- self . connect_provider_internal ( capability) . await
175+ pub async fn connect_provider_no_timeout (
176+ & self ,
177+ capability : PowerCapability ,
178+ ) -> Result < Policy < ' a , ConnectedProvider > , Error > {
179+ self . connect_provider_internal_no_timeout ( capability) . await ?;
180+ Ok ( Policy :: new ( self . device ) )
181+ }
182+
183+ /// Connect this device as a provider
184+ pub async fn connect_provider ( & self , capability : PowerCapability ) -> Result < Policy < ' a , ConnectedProvider > , Error > {
185+ self . connect_provider_internal ( capability) . await ?;
186+ Ok ( Policy :: new ( self . device ) )
121187 }
122188
123189 /// Get the provider power capability of this device
0 commit comments