aboutsummaryrefslogtreecommitdiff
path: root/embassy-net-esp-hosted/src/control.rs
diff options
context:
space:
mode:
authorUlf Lilleengen <[email protected]>2025-12-02 11:20:43 +0100
committerUlf Lilleengen <[email protected]>2025-12-02 11:20:43 +0100
commite79592c7af7b3476d2e51f5859c586b9ff8f5381 (patch)
tree6a196f718833b14c2c9804467793cc40cf6d7b32 /embassy-net-esp-hosted/src/control.rs
parentb8afe4ff5fd590903861e44224171f37b9ae6e62 (diff)
feat: support OTA commands in esp-hosted driver
* Expose OTA functionality in control * Handle OTA swap wait in runner
Diffstat (limited to 'embassy-net-esp-hosted/src/control.rs')
-rw-r--r--embassy-net-esp-hosted/src/control.rs46
1 files changed, 45 insertions, 1 deletions
diff --git a/embassy-net-esp-hosted/src/control.rs b/embassy-net-esp-hosted/src/control.rs
index 38ec648b4..d96a62daf 100644
--- a/embassy-net-esp-hosted/src/control.rs
+++ b/embassy-net-esp-hosted/src/control.rs
@@ -24,6 +24,11 @@ pub struct Control<'a> {
24 shared: &'a Shared, 24 shared: &'a Shared,
25} 25}
26 26
27/// Handle for managing firmware update.
28pub struct UpdateControl<'a, 'd> {
29 control: &'a mut Control<'d>,
30}
31
27/// WiFi mode. 32/// WiFi mode.
28#[allow(unused)] 33#[allow(unused)]
29#[derive(Copy, Clone, PartialEq, Eq, Debug)] 34#[derive(Copy, Clone, PartialEq, Eq, Debug)]
@@ -146,6 +151,13 @@ impl<'a> Control<'a> {
146 Ok(()) 151 Ok(())
147 } 152 }
148 153
154 /// Initiate a firmware update.
155 pub async fn update(&mut self) -> Result<UpdateControl<'_, 'a>, Error> {
156 let req = proto::CtrlMsg_Req_OTABegin {};
157 ioctl!(self, ReqOtaBegin, RespOtaBegin, req, resp);
158 Ok(UpdateControl { control: self })
159 }
160
149 /// duration in seconds, clamped to [10, 3600] 161 /// duration in seconds, clamped to [10, 3600]
150 async fn set_heartbeat(&mut self, duration: u32) -> Result<(), Error> { 162 async fn set_heartbeat(&mut self, duration: u32) -> Result<(), Error> {
151 let req = proto::CtrlMsg_Req_ConfigHeartbeat { 163 let req = proto::CtrlMsg_Req_ConfigHeartbeat {
@@ -175,7 +187,8 @@ impl<'a> Control<'a> {
175 async fn ioctl(&mut self, msg: &mut CtrlMsg) -> Result<(), Error> { 187 async fn ioctl(&mut self, msg: &mut CtrlMsg) -> Result<(), Error> {
176 debug!("ioctl req: {:?}", &msg); 188 debug!("ioctl req: {:?}", &msg);
177 189
178 let mut buf = [0u8; 128]; 190 // Theoretical max overhead is 29 bytes. Biggest message is OTA write with 256 bytes.
191 let mut buf = [0u8; 256 + 29];
179 let buf_len = buf.len(); 192 let buf_len = buf.len();
180 193
181 let mut encoder = PbEncoder::new(&mut buf[..]); 194 let mut encoder = PbEncoder::new(&mut buf[..]);
@@ -216,6 +229,37 @@ impl<'a> Control<'a> {
216 } 229 }
217} 230}
218 231
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
219// WHY IS THIS A STRING? WHYYYY 263// WHY IS THIS A STRING? WHYYYY
220fn parse_mac(mac: &str) -> Result<[u8; 6], Error> { 264fn parse_mac(mac: &str) -> Result<[u8; 6], Error> {
221 fn nibble_from_hex(b: u8) -> Result<u8, Error> { 265 fn nibble_from_hex(b: u8) -> Result<u8, Error> {