1use core::mem::MaybeUninit;
2
3use crate::crc::{CRC_INIT, crc16};
4use crate::sync::Sync;
5use crate::{Cmd, ReadError, Status};
6
7pub const MAX_PAYLOAD: usize = 64;
9
10#[repr(C, packed)]
15#[derive(Clone, Copy)]
16pub struct InfoData {
17 pub capacity: u32,
19 pub erase_size: u16,
21 pub boot_version: u16,
23 pub app_version: u16,
25 pub mode: u16,
27}
28
29#[repr(C)]
31#[derive(Clone, Copy)]
32pub struct EraseData {
33 pub byte_count: u16,
35}
36
37#[repr(C)]
39#[derive(Clone, Copy)]
40pub struct VerifyData {
41 pub crc: u16,
43}
44
45#[repr(C)]
50pub union Data {
51 pub raw: [u8; MAX_PAYLOAD],
53 pub info: InfoData,
55 pub erase: EraseData,
57 pub verify: VerifyData,
59}
60
61#[repr(C)]
68pub struct Frame {
69 sync: Sync,
70 pub cmd: Cmd,
72 pub status: Status,
74 pub addr: u32,
76 pub len: u16,
78 pub data: Data,
80 pub crc: [u8; 2],
82}
83
84impl Default for Frame {
85 fn default() -> Self {
88 let frame: MaybeUninit<Self> = MaybeUninit::uninit();
89 let mut frame = unsafe { frame.assume_init() };
90 frame.sync = Sync::default();
91 frame.cmd = Cmd::Info;
92 frame.status = Status::Request;
93 frame.addr = 0;
94 frame.len = 0;
95 frame.crc = [0; 2];
96 frame
97 }
98}
99
100impl Frame {
101 fn as_bytes(&self, offset: usize, len: usize) -> &[u8] {
102 debug_assert!(offset + len <= core::mem::size_of::<Self>());
103 unsafe {
104 let ptr = (self as *const Self as *const u8).add(offset);
105 core::slice::from_raw_parts(ptr, len)
106 }
107 }
108
109 fn as_bytes_mut(&mut self, offset: usize, len: usize) -> &mut [u8] {
110 debug_assert!(offset + len <= core::mem::size_of::<Self>());
111 unsafe {
112 let ptr = (self as *mut Self as *mut u8).add(offset);
113 core::slice::from_raw_parts_mut(ptr, len)
114 }
115 }
116
117 pub fn send<W: embedded_io::Write>(&mut self, w: &mut W) -> Result<(), W::Error> {
119 self.sync = Sync::valid();
120 let body_len = 10 + self.len as usize;
121 self.crc = crc16(CRC_INIT, self.as_bytes(0, body_len)).to_le_bytes();
122 w.write_all(self.as_bytes(0, body_len))?;
123 w.write_all(&self.crc)
124 }
125
126 pub fn read<R: embedded_io::Read>(&mut self, r: &mut R) -> Result<Status, ReadError> {
132 self.sync.read(r)?;
133
134 r.read_exact(self.as_bytes_mut(2, 8))
136 .map_err(|_| ReadError)?;
137
138 if !Cmd::is_valid(self.as_bytes(2, 1)[0]) || !Status::is_valid(self.as_bytes(3, 1)[0]) {
139 return Ok(Status::Unsupported);
144 }
145
146 let data_len = self.len as usize;
147
148 if data_len > MAX_PAYLOAD {
149 return Ok(Status::PayloadOverflow);
152 }
153
154 if data_len > 0 {
156 r.read_exact(unsafe { &mut self.data.raw[..data_len] })
157 .map_err(|_| ReadError)?;
158 }
159
160 r.read_exact(&mut self.crc).map_err(|_| ReadError)?;
162
163 if self.crc != crc16(CRC_INIT, self.as_bytes(0, 10 + data_len)).to_le_bytes() {
165 return Ok(Status::CrcMismatch);
166 }
167
168 Ok(Status::Ok)
169 }
170
171 pub async fn send_async<W: embedded_io_async::Write>(
173 &mut self,
174 w: &mut W,
175 ) -> Result<(), W::Error> {
176 self.sync = Sync::valid();
177 let body_len = 10 + self.len as usize;
178 self.crc = crc16(CRC_INIT, self.as_bytes(0, body_len)).to_le_bytes();
179 w.write_all(self.as_bytes(0, body_len)).await?;
180 w.write_all(&self.crc).await
181 }
182
183 pub async fn read_async<R: embedded_io_async::Read>(
185 &mut self,
186 r: &mut R,
187 ) -> Result<Status, ReadError> {
188 self.sync.read_async(r).await?;
189
190 r.read_exact(self.as_bytes_mut(2, 8))
191 .await
192 .map_err(|_| ReadError)?;
193
194 if !Cmd::is_valid(self.as_bytes(2, 1)[0]) || !Status::is_valid(self.as_bytes(3, 1)[0]) {
195 return Ok(Status::Unsupported);
197 }
198
199 let data_len = self.len as usize;
200
201 if data_len > MAX_PAYLOAD {
202 return Ok(Status::PayloadOverflow);
204 }
205
206 if data_len > 0 {
207 r.read_exact(unsafe { &mut self.data.raw[..data_len] })
208 .await
209 .map_err(|_| ReadError)?;
210 }
211
212 r.read_exact(&mut self.crc).await.map_err(|_| ReadError)?;
213
214 if self.crc != crc16(CRC_INIT, self.as_bytes(0, 10 + data_len)).to_le_bytes() {
215 return Ok(Status::CrcMismatch);
216 }
217
218 Ok(Status::Ok)
219 }
220}
221
222#[cfg(test)]
223mod tests {
224 use super::*;
225
226 struct MockReader<'a> {
227 data: &'a [u8],
228 pos: usize,
229 }
230
231 impl<'a> MockReader<'a> {
232 fn new(data: &'a [u8]) -> Self {
233 Self { data, pos: 0 }
234 }
235 }
236
237 impl embedded_io::ErrorType for MockReader<'_> {
238 type Error = core::convert::Infallible;
239 }
240
241 impl embedded_io::Read for MockReader<'_> {
242 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
243 let n = buf.len().min(self.data.len() - self.pos);
244 buf[..n].copy_from_slice(&self.data[self.pos..self.pos + n]);
245 self.pos += n;
246 Ok(n)
247 }
248 }
249
250 struct Sink {
251 buf: [u8; 512],
252 pos: usize,
253 }
254
255 impl Sink {
256 fn new() -> Self {
257 Self {
258 buf: [0; 512],
259 pos: 0,
260 }
261 }
262 fn written(&self) -> &[u8] {
263 &self.buf[..self.pos]
264 }
265 }
266
267 impl embedded_io::ErrorType for Sink {
268 type Error = core::convert::Infallible;
269 }
270
271 impl embedded_io::Write for Sink {
272 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
273 let n = buf.len().min(self.buf.len() - self.pos);
274 self.buf[self.pos..self.pos + n].copy_from_slice(&buf[..n]);
275 self.pos += n;
276 Ok(n)
277 }
278 fn flush(&mut self) -> Result<(), Self::Error> {
279 Ok(())
280 }
281 }
282
283 fn frame(cmd: Cmd, status: Status, addr: u32, data: &[u8]) -> Frame {
284 let mut f = Frame {
285 cmd,
286 status,
287 addr,
288 len: data.len() as u16,
289 ..Default::default()
290 };
291 unsafe { f.data.raw[..data.len()].copy_from_slice(data) };
292 f
293 }
294
295 #[test]
296 fn request_round_trip() {
297 let mut frame = frame(Cmd::Write, Status::Request, 0x0800, &[0xDE, 0xAD]);
298
299 let mut sink = Sink::new();
300 frame.send(&mut sink).unwrap();
301
302 let mut frame2 = Frame::default();
303 frame2.read(&mut MockReader::new(sink.written())).unwrap();
304 assert_eq!(frame2.cmd, Cmd::Write);
305 assert_eq!(frame2.len, 2);
306 assert_eq!(frame2.addr, 0x0800);
307 assert_eq!(frame2.status, Status::Request);
308 assert_eq!(unsafe { &frame2.data.raw[..2] }, &[0xDE, 0xAD]);
309 assert_eq!(frame2.crc, frame.crc);
310 }
311
312 #[test]
313 fn response_round_trip() {
314 let mut frame = frame(Cmd::Verify, Status::Ok, 0, &[0x12, 0x34]);
315
316 let mut sink = Sink::new();
317 frame.send(&mut sink).unwrap();
318
319 let mut frame2 = Frame::default();
320 frame2.read(&mut MockReader::new(sink.written())).unwrap();
321 assert_eq!(frame2.cmd, Cmd::Verify);
322 assert_eq!(frame2.status, Status::Ok);
323 assert_eq!(unsafe { &frame2.data.raw[..2] }, &[0x12, 0x34]);
324 }
325
326 #[test]
327 fn request_no_data() {
328 let mut frame = frame(Cmd::Erase, Status::Request, 0, &[]);
329
330 let mut sink = Sink::new();
331 frame.send(&mut sink).unwrap();
332
333 assert_eq!(sink.written().len(), 12);
335
336 let mut frame2 = Frame::default();
337 frame2.read(&mut MockReader::new(sink.written())).unwrap();
338 assert_eq!(frame2.cmd, Cmd::Erase);
339 assert_eq!(frame2.len, 0);
340 }
341
342 #[test]
343 fn large_addr_round_trip() {
344 let mut frame = frame(Cmd::Write, Status::Request, 0x0001_0800, &[0xAB]);
345
346 let mut sink = Sink::new();
347 frame.send(&mut sink).unwrap();
348
349 let mut frame2 = Frame::default();
350 frame2.read(&mut MockReader::new(sink.written())).unwrap();
351 assert_eq!(frame2.addr, 0x0001_0800);
352 }
353
354 #[test]
355 fn cmd_addr_carry_over() {
356 let mut frame = frame(Cmd::Write, Status::Request, 0x0400, &[0xAB, 0xCD]);
357
358 let mut sink = Sink::new();
359 frame.send(&mut sink).unwrap();
360
361 let mut dev = Frame::default();
363 dev.read(&mut MockReader::new(sink.written())).unwrap();
364
365 dev.status = Status::Ok;
367 dev.len = 0;
368 let mut resp_sink = Sink::new();
369 dev.send(&mut resp_sink).unwrap();
370
371 let mut host = Frame::default();
373 host.read(&mut MockReader::new(resp_sink.written()))
374 .unwrap();
375 assert_eq!(host.cmd, Cmd::Write);
376 assert_eq!(host.addr, 0x0400);
377 assert_eq!(host.status, Status::Ok);
378 }
379
380 #[test]
381 fn read_bad_cmd() {
382 let mut frame = frame(Cmd::Info, Status::Request, 0, &[]);
383
384 let mut sink = Sink::new();
385 frame.send(&mut sink).unwrap();
386 sink.buf[2] ^= 0xFF; let mut frame2 = Frame::default();
389 assert_eq!(
390 frame2.read(&mut MockReader::new(sink.written())),
391 Ok(Status::Unsupported)
392 );
393 }
394
395 #[test]
396 fn read_after_garbage() {
397 let mut frame = frame(Cmd::Verify, Status::Request, 0, &[]);
398
399 let mut sink = Sink::new();
400 frame.send(&mut sink).unwrap();
401 let frame_len = sink.pos;
402
403 let mut input = [0u8; 4 + 512];
404 input[..4].copy_from_slice(&[0xFF, 0x00, 0xAA, 0x42]);
405 input[4..4 + frame_len].copy_from_slice(&sink.buf[..frame_len]);
406
407 let mut frame2 = Frame::default();
408 assert_eq!(
409 frame2.read(&mut MockReader::new(&input[..4 + frame_len])),
410 Ok(Status::Ok)
411 );
412 assert_eq!(frame2.cmd, Cmd::Verify);
413 }
414
415 #[test]
416 fn read_overflow() {
417 let mut f = frame(Cmd::Write, Status::Request, 0, &[]);
419
420 let mut sink = Sink::new();
421 f.send(&mut sink).unwrap();
422
423 let overflow_len = (MAX_PAYLOAD as u16 + 1).to_le_bytes();
425 sink.buf[8] = overflow_len[0];
426 sink.buf[9] = overflow_len[1];
427
428 let mut frame2 = Frame::default();
429 assert_eq!(
430 frame2.read(&mut MockReader::new(sink.written())),
431 Ok(Status::PayloadOverflow)
432 );
433 }
434}