aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Lilleengen <[email protected]>2025-12-02 12:30:53 +0100
committerUlf Lilleengen <[email protected]>2025-12-02 12:30:53 +0100
commit4e56caa71035ab236b11b31af618a7ae45792358 (patch)
treebd90ee6b7862c87ece6002e236f482620c21942d
parent741b09ac8a0cb47285568e4e317ef8e4f7ac566e (diff)
chore: refactor api to allow other control commands
-rw-r--r--embassy-net-esp-hosted/src/control.rs81
-rw-r--r--embassy-net-esp-hosted/src/ioctl.rs1
-rw-r--r--embassy-net-esp-hosted/src/lib.rs3
3 files changed, 47 insertions, 38 deletions
diff --git a/embassy-net-esp-hosted/src/control.rs b/embassy-net-esp-hosted/src/control.rs
index d96a62daf..255ad7045 100644
--- a/embassy-net-esp-hosted/src/control.rs
+++ b/embassy-net-esp-hosted/src/control.rs
@@ -1,3 +1,4 @@
1use core::marker::PhantomData;
1use embassy_net_driver_channel as ch; 2use embassy_net_driver_channel as ch;
2use embassy_net_driver_channel::driver::{HardwareAddress, LinkState}; 3use embassy_net_driver_channel::driver::{HardwareAddress, LinkState};
3use heapless::String; 4use heapless::String;
@@ -24,9 +25,15 @@ pub struct Control<'a> {
24 shared: &'a Shared, 25 shared: &'a Shared,
25} 26}
26 27
27/// Handle for managing firmware update. 28/// Token required for doing an update
28pub struct UpdateControl<'a, 'd> { 29pub struct OtaToken {
29 control: &'a mut Control<'d>, 30 _d: PhantomData<()>,
31}
32
33impl OtaToken {
34 fn new() -> Self {
35 Self { _d: PhantomData }
36 }
30} 37}
31 38
32/// WiFi mode. 39/// WiFi mode.
@@ -152,10 +159,43 @@ impl<'a> Control<'a> {
152 } 159 }
153 160
154 /// Initiate a firmware update. 161 /// Initiate a firmware update.
155 pub async fn update(&mut self) -> Result<UpdateControl<'_, 'a>, Error> { 162 ///
163 /// Returns a token needed for writing and finishing.
164 pub async fn ota_begin(&mut self) -> Result<OtaToken, Error> {
156 let req = proto::CtrlMsg_Req_OTABegin {}; 165 let req = proto::CtrlMsg_Req_OTABegin {};
157 ioctl!(self, ReqOtaBegin, RespOtaBegin, req, resp); 166 ioctl!(self, ReqOtaBegin, RespOtaBegin, req, resp);
158 Ok(UpdateControl { control: self }) 167 Ok(OtaToken::new())
168 }
169
170 /// Write slice of firmware to a device.
171 ///
172 /// Token is required as proof that ota_begin was called.
173 ///
174 /// The slice is split into chunks that can be sent across
175 /// the ioctl protocol to the wifi adapter.
176 pub async fn ota_write(&mut self, _token: &OtaToken, data: &[u8]) -> Result<(), Error> {
177 for chunk in data.chunks(256) {
178 let req = proto::CtrlMsg_Req_OTAWrite {
179 ota_data: heapless::Vec::from_slice(chunk).unwrap(),
180 };
181 ioctl!(self, ReqOtaWrite, RespOtaWrite, req, resp);
182 }
183 Ok(())
184 }
185
186 /// End the OTA session.
187 ///
188 /// Token is required as proof that ota_begin was called.
189 ///
190 /// NOTE: Will reset the wifi adapter after 5 seconds.
191 pub async fn ota_end(&mut self, _token: OtaToken) -> Result<(), Error> {
192 let req = proto::CtrlMsg_Req_OTAEnd {};
193 ioctl!(self, ReqOtaEnd, RespOtaEnd, req, resp);
194 // Ensures that run loop awaits reset
195 self.shared.ota_done();
196 // Wait for re-init
197 self.init().await?;
198 Ok(())
159 } 199 }
160 200
161 /// duration in seconds, clamped to [10, 3600] 201 /// duration in seconds, clamped to [10, 3600]
@@ -229,37 +269,6 @@ impl<'a> Control<'a> {
229 } 269 }
230} 270}
231 271
232impl<'a, 'd> UpdateControl<'a, 'd> {
233 /// Write slice of firmware to a device.
234 ///
235 /// The slice is split into chunks that can be sent across
236 /// the ioctl protocol to the wifi adapter.
237 pub async fn write(&mut self, data: &[u8]) -> Result<(), Error> {
238 let this = &mut self.control;
239 for chunk in data.chunks(256) {
240 let req = proto::CtrlMsg_Req_OTAWrite {
241 ota_data: heapless::Vec::from_slice(chunk).unwrap(),
242 };
243 ioctl!(this, ReqOtaWrite, RespOtaWrite, req, resp);
244 }
245 Ok(())
246 }
247
248 /// End the OTA session.
249 ///
250 /// NOTE: Will reset the wifi adapter after 5 seconds.
251 pub async fn finish(self) -> Result<(), Error> {
252 let this = self.control;
253 let req = proto::CtrlMsg_Req_OTAEnd {};
254 ioctl!(this, ReqOtaEnd, RespOtaEnd, req, resp);
255 // Ensures that run loop awaits reset
256 this.shared.ota_done();
257 // Wait for re-init
258 this.init().await?;
259 Ok(())
260 }
261}
262
263// WHY IS THIS A STRING? WHYYYY 272// WHY IS THIS A STRING? WHYYYY
264fn parse_mac(mac: &str) -> Result<[u8; 6], Error> { 273fn parse_mac(mac: &str) -> Result<[u8; 6], Error> {
265 fn nibble_from_hex(b: u8) -> Result<u8, Error> { 274 fn nibble_from_hex(b: u8) -> Result<u8, Error> {
diff --git a/embassy-net-esp-hosted/src/ioctl.rs b/embassy-net-esp-hosted/src/ioctl.rs
index 7f462d528..8b9d582be 100644
--- a/embassy-net-esp-hosted/src/ioctl.rs
+++ b/embassy-net-esp-hosted/src/ioctl.rs
@@ -106,7 +106,6 @@ impl Shared {
106 let mut this = self.0.borrow_mut(); 106 let mut this = self.0.borrow_mut();
107 this.is_ota = true; 107 this.is_ota = true;
108 this.is_init = false; 108 this.is_init = false;
109 this.runner_waker.wake();
110 } 109 }
111 110
112 // check if ota is in progress 111 // check if ota is in progress
diff --git a/embassy-net-esp-hosted/src/lib.rs b/embassy-net-esp-hosted/src/lib.rs
index 7236e73e8..f0cf04d04 100644
--- a/embassy-net-esp-hosted/src/lib.rs
+++ b/embassy-net-esp-hosted/src/lib.rs
@@ -238,8 +238,9 @@ where
238 if self.shared.is_ota() { 238 if self.shared.is_ota() {
239 self.heartbeat_deadline = Instant::now() + HEARTBEAT_MAX_GAP; 239 self.heartbeat_deadline = Instant::now() + HEARTBEAT_MAX_GAP;
240 continue; 240 continue;
241 } else {
242 panic!("heartbeat from esp32 stopped")
241 } 243 }
242 panic!("heartbeat from esp32 stopped")
243 } 244 }
244 } 245 }
245 246