diff options
| author | Ulf Lilleengen <[email protected]> | 2025-12-02 11:20:43 +0100 |
|---|---|---|
| committer | Ulf Lilleengen <[email protected]> | 2025-12-02 11:20:43 +0100 |
| commit | e79592c7af7b3476d2e51f5859c586b9ff8f5381 (patch) | |
| tree | 6a196f718833b14c2c9804467793cc40cf6d7b32 /embassy-net-esp-hosted/src/control.rs | |
| parent | b8afe4ff5fd590903861e44224171f37b9ae6e62 (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.rs | 46 |
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. | ||
| 28 | pub 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 | ||
| 232 | impl<'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 |
| 220 | fn parse_mac(mac: &str) -> Result<[u8; 6], Error> { | 264 | fn 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> { |
