diff options
| author | Ulf Lilleengen <[email protected]> | 2025-12-02 12:30:53 +0100 |
|---|---|---|
| committer | Ulf Lilleengen <[email protected]> | 2025-12-02 12:30:53 +0100 |
| commit | 4e56caa71035ab236b11b31af618a7ae45792358 (patch) | |
| tree | bd90ee6b7862c87ece6002e236f482620c21942d | |
| parent | 741b09ac8a0cb47285568e4e317ef8e4f7ac566e (diff) | |
chore: refactor api to allow other control commands
| -rw-r--r-- | embassy-net-esp-hosted/src/control.rs | 81 | ||||
| -rw-r--r-- | embassy-net-esp-hosted/src/ioctl.rs | 1 | ||||
| -rw-r--r-- | embassy-net-esp-hosted/src/lib.rs | 3 |
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 @@ | |||
| 1 | use core::marker::PhantomData; | ||
| 1 | use embassy_net_driver_channel as ch; | 2 | use embassy_net_driver_channel as ch; |
| 2 | use embassy_net_driver_channel::driver::{HardwareAddress, LinkState}; | 3 | use embassy_net_driver_channel::driver::{HardwareAddress, LinkState}; |
| 3 | use heapless::String; | 4 | use 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 |
| 28 | pub struct UpdateControl<'a, 'd> { | 29 | pub struct OtaToken { |
| 29 | control: &'a mut Control<'d>, | 30 | _d: PhantomData<()>, |
| 31 | } | ||
| 32 | |||
| 33 | impl 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 | ||
| 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 | |||
| 263 | // WHY IS THIS A STRING? WHYYYY | 272 | // WHY IS THIS A STRING? WHYYYY |
| 264 | fn parse_mac(mac: &str) -> Result<[u8; 6], Error> { | 273 | fn 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 | ||
