cameleon_device/u3v/protocol/
cmd.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use std::{convert::TryInto, io::Write};
6
7use cameleon_impl::bytes_io::WriteBytes;
8
9use crate::u3v::{Error, Result};
10
11#[derive(Debug)]
12pub struct CommandPacket<T> {
13    ccd: CommandCcd,
14    scd: T,
15}
16
17impl<T> CommandPacket<T>
18where
19    T: CommandScd,
20{
21    const PREFIX_MAGIC: u32 = 0x4356_3355;
22
23    // Magic + CCD length.
24    const ACK_HEADER_LENGTH: usize = 4 + 8;
25
26    // Length of pending ack SCD. This SCD can be returned with any command.
27    const MINIMUM_ACK_SCD_LENGTH: u16 = 4;
28
29    pub fn serialize(&self, mut buf: impl Write) -> Result<()> {
30        buf.write_bytes_le(Self::PREFIX_MAGIC)?;
31        self.ccd.serialize(&mut buf)?;
32        self.scd.serialize(&mut buf)?;
33
34        Ok(())
35    }
36
37    pub fn ccd(&self) -> &CommandCcd {
38        &self.ccd
39    }
40
41    pub fn scd(&self) -> &T {
42        &self.scd
43    }
44
45    pub fn cmd_len(&self) -> usize {
46        // Magic(4bytes) + ccd + scd
47        4 + CommandCcd::len() as usize + self.scd.scd_len() as usize
48    }
49
50    pub fn request_id(&self) -> u16 {
51        self.ccd.request_id
52    }
53
54    /// Maximum length of corresponding ack packet.
55    pub fn maximum_ack_len(&self) -> usize {
56        let scd_len = self.scd.ack_scd_len();
57        let maximum_scd_length = std::cmp::max(scd_len, Self::MINIMUM_ACK_SCD_LENGTH) as usize;
58
59        Self::ACK_HEADER_LENGTH + maximum_scd_length
60    }
61
62    pub fn new(scd: T, request_id: u16) -> Self {
63        let ccd = CommandCcd::from_scd(&scd, request_id);
64        Self { ccd, scd }
65    }
66
67    fn header_len() -> usize {
68        4 + CommandCcd::len() as usize
69    }
70}
71
72#[derive(Clone, Debug, PartialEq, Eq)]
73pub struct ReadMem {
74    pub(crate) address: u64,
75    pub(crate) read_length: u16,
76}
77
78pub struct ReadMemChunks {
79    address: u64,
80    read_length: u16,
81    maximum_read_length: usize,
82}
83
84impl std::iter::Iterator for ReadMemChunks {
85    type Item = ReadMem;
86
87    fn next(&mut self) -> Option<ReadMem> {
88        if self.read_length == 0 {
89            return None;
90        }
91
92        if self.read_length as usize > self.maximum_read_length {
93            let next_item = ReadMem::new(self.address, self.maximum_read_length as u16);
94            self.read_length -= self.maximum_read_length as u16;
95            self.address += self.maximum_read_length as u64;
96            Some(next_item)
97        } else {
98            let next_item = ReadMem::new(self.address, self.read_length);
99            self.read_length = 0;
100            Some(next_item)
101        }
102    }
103}
104
105impl ReadMem {
106    #[must_use]
107    pub fn new(address: u64, read_length: u16) -> Self {
108        Self {
109            address,
110            read_length,
111        }
112    }
113
114    /// Split into multiple [`ReadMem`] chunks so that all corresponding ack length fit into `ack_len`.
115    pub fn chunks(&self, ack_len: usize) -> Result<ReadMemChunks> {
116        let ack_header_length = CommandPacket::<ReadMem>::ACK_HEADER_LENGTH;
117        if ack_len <= ack_header_length {
118            let msg = format!(
119                "ack length must be larger than {}",
120                CommandPacket::<ReadMem>::ACK_HEADER_LENGTH
121            );
122            return Err(Error::InvalidPacket(msg.into()));
123        };
124        let maximum_read_length = ack_len - ack_header_length;
125
126        Ok(ReadMemChunks {
127            address: self.address,
128            read_length: self.read_length,
129            maximum_read_length,
130        })
131    }
132
133    /// Returns maximum read length that corresponding ack length fit into `maximum_ack_len`.
134    pub fn maximum_read_length(maximum_ack_len: usize) -> u16 {
135        (maximum_ack_len - CommandPacket::<ReadMem>::ACK_HEADER_LENGTH)
136            .try_into()
137            .unwrap_or(u16::MAX)
138    }
139
140    #[must_use]
141    pub fn read_length(&self) -> u16 {
142        self.read_length
143    }
144}
145
146#[derive(Clone, Debug, PartialEq, Eq)]
147pub struct WriteMem<'a> {
148    pub(crate) address: u64,
149    pub(crate) data: &'a [u8],
150    data_len: u16,
151    len: u16,
152}
153
154pub struct WriteMemChunks<'a> {
155    address: u64,
156    data: &'a [u8],
157    data_idx: usize,
158    maximum_data_len: usize,
159}
160
161impl<'a> std::iter::Iterator for WriteMemChunks<'a> {
162    type Item = WriteMem<'a>;
163
164    fn next(&mut self) -> Option<Self::Item> {
165        if self.data_idx == self.data.len() {
166            return None;
167        }
168
169        if self.data_idx + self.maximum_data_len < self.data.len() {
170            let next_item = WriteMem::new(
171                self.address,
172                &self.data[self.data_idx..self.data_idx + self.maximum_data_len],
173            )
174            .unwrap();
175            self.address += self.maximum_data_len as u64;
176            self.data_idx += self.maximum_data_len;
177            Some(next_item)
178        } else {
179            let next_item = WriteMem::new(self.address, &self.data[self.data_idx..]).unwrap();
180            self.data_idx = self.data.len();
181            Some(next_item)
182        }
183    }
184}
185
186impl<'a> WriteMem<'a> {
187    pub fn new(address: u64, data: &'a [u8]) -> Result<Self> {
188        let data_len = into_scd_len(data.len())?;
189        let len = into_scd_len(data.len() + 8)?;
190
191        Ok(Self {
192            address,
193            data,
194            data_len,
195            len,
196        })
197    }
198
199    /// Data length of the
200    #[must_use]
201    pub fn data_len(&self) -> usize {
202        self.data.len()
203    }
204
205    /// Split into multiple [`WriteMem`] chunks so that all commands resulting from chunks fit into `cmd_len`.
206    pub fn chunks(&self, cmd_len: usize) -> Result<WriteMemChunks<'a>> {
207        let cmd_header_len = CommandPacket::<WriteMem>::header_len() + 8;
208        if cmd_len <= cmd_header_len {
209            let msg = format!(
210                "cmd_len must be larger than {}",
211                CommandPacket::<WriteMem>::header_len() + 8
212            );
213            return Err(Error::InvalidPacket(msg.into()));
214        };
215        let maximum_data_len = cmd_len - cmd_header_len;
216
217        Ok(WriteMemChunks {
218            address: self.address,
219            data: self.data,
220            data_idx: 0,
221            maximum_data_len,
222        })
223    }
224}
225
226#[derive(Clone, Debug, PartialEq, Eq)]
227pub struct ReadMemStacked {
228    pub(crate) entries: Vec<ReadMem>,
229    len: u16,
230    ack_scd_len: u16,
231}
232
233impl ReadMemStacked {
234    pub fn new(entries: Vec<ReadMem>) -> Result<Self> {
235        let len = Self::len(&entries)?;
236        let ack_scd_len = Self::ack_scd_len(&entries)?;
237
238        Ok(Self {
239            entries,
240            len,
241            ack_scd_len,
242        })
243    }
244
245    fn len(regs: &[ReadMem]) -> Result<u16> {
246        let len = regs.iter().fold(0, |acc, reg| acc + reg.scd_len() as usize);
247        into_scd_len(len)
248    }
249
250    fn ack_scd_len(entries: &[ReadMem]) -> Result<u16> {
251        let mut acc: u16 = 0;
252        for ent in entries {
253            acc = acc.checked_add(ent.read_length).ok_or_else(|| {
254                Error::InvalidPacket("total read length must be less than u16::MAX".into())
255            })?;
256        }
257
258        Ok(acc)
259    }
260}
261
262#[derive(Clone, Debug, PartialEq, Eq)]
263pub struct WriteMemStacked<'a> {
264    pub(crate) entries: Vec<WriteMem<'a>>,
265    len: u16,
266    ack_scd_len: u16,
267}
268
269impl<'a> WriteMemStacked<'a> {
270    pub fn new(entries: Vec<WriteMem<'a>>) -> Result<Self> {
271        let len = Self::len(&entries)?;
272        let ack_scd_len = entries.len() as u16 * 4;
273        Ok(Self {
274            entries,
275            len,
276            ack_scd_len,
277        })
278    }
279
280    fn len(entries: &[WriteMem<'a>]) -> Result<u16> {
281        let len = entries
282            .iter()
283            .fold(0, |acc, cmd| acc + 12 + cmd.data_len as usize);
284        into_scd_len(len)
285    }
286}
287
288#[derive(Clone, Debug, PartialEq, Eq)]
289pub struct CommandCcd {
290    flag: CommandFlag,
291    scd_kind: ScdKind,
292    scd_len: u16,
293    request_id: u16,
294}
295
296impl CommandCcd {
297    #[must_use]
298    pub fn flag(&self) -> CommandFlag {
299        self.flag
300    }
301
302    #[must_use]
303    pub fn scd_kind(&self) -> ScdKind {
304        self.scd_kind
305    }
306
307    #[must_use]
308    pub fn scd_len(&self) -> u16 {
309        self.scd_len
310    }
311
312    #[must_use]
313    pub fn request_id(&self) -> u16 {
314        self.request_id
315    }
316
317    pub(crate) fn new(flag: CommandFlag, scd_kind: ScdKind, scd_len: u16, request_id: u16) -> Self {
318        Self {
319            flag,
320            scd_kind,
321            scd_len,
322            request_id,
323        }
324    }
325
326    fn from_scd(scd: &impl CommandScd, request_id: u16) -> Self {
327        Self::new(scd.flag(), scd.scd_kind(), scd.scd_len(), request_id)
328    }
329
330    fn serialize(&self, mut buf: impl Write) -> Result<()> {
331        self.flag.serialize(&mut buf)?;
332        self.scd_kind.serialize(&mut buf)?;
333        buf.write_bytes_le(self.scd_len)?;
334
335        buf.write_bytes_le(self.request_id)?;
336        Ok(())
337    }
338
339    #[must_use]
340    pub const fn len() -> u16 {
341        // flags(2bytes) + command_id(2bytes) + scd_len(2bytes) + request_id(2bytes)
342        8
343    }
344}
345
346#[derive(Clone, Copy, Debug, PartialEq, Eq)]
347pub enum CommandFlag {
348    RequestAck,
349    CommandResend,
350}
351
352impl CommandFlag {
353    fn serialize(self, mut buf: impl Write) -> Result<()> {
354        let flag_id: u16 = match self {
355            Self::RequestAck => 1 << 14,
356            Self::CommandResend => 1 << 15,
357        };
358
359        buf.write_bytes_le(flag_id)?;
360        Ok(())
361    }
362}
363
364#[derive(Clone, Copy, Debug, PartialEq, Eq)]
365pub enum ScdKind {
366    ReadMem,
367    WriteMem,
368    ReadMemStacked,
369    WriteMemStacked,
370}
371
372impl ScdKind {
373    fn serialize(self, mut buf: impl Write) -> Result<()> {
374        let kind_id: u16 = match self {
375            Self::ReadMem => 0x0800,
376            Self::WriteMem => 0x0802,
377            Self::ReadMemStacked => 0x0806,
378            Self::WriteMemStacked => 0x0808,
379        };
380
381        buf.write_bytes_le(kind_id)?;
382        Ok(())
383    }
384}
385
386pub trait CommandScd: std::fmt::Debug + Sized {
387    fn flag(&self) -> CommandFlag;
388
389    fn scd_kind(&self) -> ScdKind;
390
391    fn scd_len(&self) -> u16;
392
393    fn serialize(&self, buf: impl Write) -> Result<()>;
394
395    fn ack_scd_len(&self) -> u16;
396
397    fn finalize(self, request_id: u16) -> CommandPacket<Self> {
398        CommandPacket::new(self, request_id)
399    }
400}
401
402impl CommandScd for ReadMem {
403    fn flag(&self) -> CommandFlag {
404        CommandFlag::RequestAck
405    }
406
407    fn scd_kind(&self) -> ScdKind {
408        ScdKind::ReadMem
409    }
410
411    fn scd_len(&self) -> u16 {
412        // Address(8 bytes) + reserved(2bytes) + length(2 bytes)
413        12
414    }
415
416    fn serialize(&self, mut buf: impl Write) -> Result<()> {
417        buf.write_bytes_le(self.address)?;
418        buf.write_bytes_le(0_u16)?; // 2bytes reserved.
419        buf.write_bytes_le(self.read_length)?;
420        Ok(())
421    }
422
423    fn ack_scd_len(&self) -> u16 {
424        self.read_length
425    }
426}
427
428impl CommandScd for WriteMem<'_> {
429    fn flag(&self) -> CommandFlag {
430        CommandFlag::RequestAck
431    }
432
433    fn scd_kind(&self) -> ScdKind {
434        ScdKind::WriteMem
435    }
436
437    fn scd_len(&self) -> u16 {
438        self.len
439    }
440
441    fn serialize(&self, mut buf: impl Write) -> Result<()> {
442        buf.write_bytes_le(self.address)?;
443        buf.write_all(self.data)?;
444        Ok(())
445    }
446
447    fn ack_scd_len(&self) -> u16 {
448        // Reserved(2bytes)+ length written(2bytes);
449        4
450    }
451}
452
453impl CommandScd for ReadMemStacked {
454    fn flag(&self) -> CommandFlag {
455        CommandFlag::RequestAck
456    }
457
458    fn scd_kind(&self) -> ScdKind {
459        ScdKind::ReadMemStacked
460    }
461
462    fn scd_len(&self) -> u16 {
463        self.len
464    }
465
466    fn serialize(&self, mut buf: impl Write) -> Result<()> {
467        for ent in &self.entries {
468            ent.serialize(&mut buf)?;
469        }
470        Ok(())
471    }
472
473    fn ack_scd_len(&self) -> u16 {
474        self.ack_scd_len
475    }
476}
477
478impl CommandScd for WriteMemStacked<'_> {
479    fn flag(&self) -> CommandFlag {
480        CommandFlag::RequestAck
481    }
482
483    fn scd_kind(&self) -> ScdKind {
484        ScdKind::WriteMemStacked
485    }
486
487    fn scd_len(&self) -> u16 {
488        // Each register is composed of [address(8bytes), reserved(2bytes), data_len(2bytes), data(len bytes)]
489        self.len
490    }
491
492    fn serialize(&self, mut buf: impl Write) -> Result<()> {
493        for ent in &self.entries {
494            buf.write_bytes_le(ent.address)?;
495            buf.write_bytes_le(0_u16)?; // 2bytes reserved.
496            buf.write_bytes_le(ent.data_len)?;
497            buf.write_all(ent.data)?;
498        }
499        Ok(())
500    }
501
502    fn ack_scd_len(&self) -> u16 {
503        self.ack_scd_len
504    }
505}
506
507fn into_scd_len(len: usize) -> Result<u16> {
508    len.try_into()
509        .map_err(|_| Error::InvalidPacket("scd length must be less than u16::MAX".into()))
510}
511
512#[cfg(test)]
513mod tests {
514    use super::*;
515
516    const HEADER_LEN: u8 = 4 + 8; // Magic + CCD.
517
518    fn serialize_header(command_id: [u8; 2], scd_len: [u8; 2], req_id: [u8; 2]) -> Vec<u8> {
519        let mut ccd = vec![];
520        ccd.write_bytes_le(0x4356_3355_u32).unwrap(); // Magic.
521        ccd.extend([0x00, 0x40]); // Packet flag: Request Ack.
522        ccd.extend(command_id);
523        ccd.extend(scd_len);
524        ccd.extend(req_id);
525        ccd
526    }
527
528    #[test]
529    fn test_read_mem_cmd() {
530        let command = ReadMem::new(0x0004, 64).finalize(1);
531        let scd_len = 12;
532
533        assert_eq!(command.cmd_len(), (HEADER_LEN + scd_len).into());
534        assert_eq!(command.request_id(), 1);
535
536        let mut buf = vec![];
537        command.serialize(&mut buf).unwrap();
538        let mut expected = serialize_header([0x00, 0x08], [scd_len, 0x00], [0x01, 0x00]);
539        expected.extend(vec![0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); // Address.
540        expected.extend(vec![0x00, 0x00]); // Reserved.
541        expected.extend(vec![64, 0x00]); // Read length.
542
543        assert_eq!(buf, expected);
544    }
545
546    #[test]
547    fn test_write_mem_cmd() {
548        let command = WriteMem::new(0x0004, &[0x01, 0x02, 0x03])
549            .unwrap()
550            .finalize(1);
551        let scd_len = 11;
552
553        assert_eq!(command.cmd_len(), (HEADER_LEN + scd_len).into());
554        assert_eq!(command.request_id(), 1);
555
556        let mut buf = vec![];
557        command.serialize(&mut buf).unwrap();
558        let mut expected = serialize_header([0x02, 0x08], [scd_len, 0x00], [0x01, 0x00]);
559        expected.extend(vec![0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); // Address.
560        expected.extend(vec![0x01, 0x02, 0x03]); // Data.
561
562        assert_eq!(buf, expected);
563    }
564
565    #[test]
566    fn test_read_mem_stacked() {
567        let read_mems = vec![ReadMem::new(0x0004, 4), ReadMem::new(0x0008, 8)];
568        let command = ReadMemStacked::new(read_mems).unwrap().finalize(1);
569        let scd_len = 12 * 2;
570
571        assert_eq!(command.cmd_len(), (HEADER_LEN + scd_len).into());
572        assert_eq!(command.request_id(), 1);
573
574        let mut buf = vec![];
575        command.serialize(&mut buf).unwrap();
576        let mut expected = serialize_header([0x06, 0x08], [12 * 2, 0x00], [0x01, 0x00]);
577        expected.extend(vec![0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); // Address 0.
578        expected.extend(vec![0x00, 0x00]); // Reserved 0.
579        expected.extend(vec![4, 0x00]); // Read length 0.
580        expected.extend(vec![0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); // Address 1.
581        expected.extend(vec![0x00, 0x00]); // Reserved 1.
582        expected.extend(vec![8, 0x00]); // Read length 1.
583
584        assert_eq!(buf, expected);
585    }
586
587    #[test]
588    fn test_write_mem_stacked() {
589        let write_mems = vec![
590            WriteMem::new(0x0004, &[0x01, 0x02, 0x03, 0x04]).unwrap(),
591            WriteMem::new(0x0008, &[0x11, 0x12, 0x13, 0x14]).unwrap(),
592        ];
593
594        let command = WriteMemStacked::new(write_mems).unwrap().finalize(1);
595        let scd_len = (12 + 4) * 2;
596
597        assert_eq!(command.cmd_len(), (HEADER_LEN + scd_len).into());
598        assert_eq!(command.request_id(), 1);
599
600        let mut buf = vec![];
601        command.serialize(&mut buf).unwrap();
602        let mut expected = serialize_header([0x08, 0x08], [scd_len, 0x00], [0x01, 0x00]);
603        expected.extend(vec![0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); // Address 0.
604        expected.extend(vec![0x00, 0x00]); // Reserved 0.
605        expected.extend(vec![4, 0x00]); // Length data block 0.
606        expected.extend(vec![0x01, 0x02, 0x03, 0x04]); // Data block 0.
607        expected.extend(vec![0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); // Address 1.
608        expected.extend(vec![0x00, 0x00]); // Reserved 1.
609        expected.extend(vec![4, 0x00]); // Length data block 1.
610        expected.extend(vec![0x11, 0x12, 0x13, 0x14]); // Data block 1.
611
612        assert_eq!(buf, expected);
613    }
614
615    #[test]
616    fn test_read_mem_chunks() {
617        let read_mem = ReadMem::new(0, 128);
618        let chunks: Vec<_> = read_mem.chunks(24).unwrap().collect();
619
620        let mut expected_addr = 0;
621        let mut read_len = 0;
622        for (i, chunk) in chunks.iter().enumerate().take(chunks.len() - 1) {
623            assert_eq!(chunk.address, expected_addr);
624            expected_addr += u64::from(chunk.read_length);
625            read_len += chunk.read_length;
626            assert_eq!(chunk.clone().finalize(i as u16).maximum_ack_len(), 24);
627        }
628
629        let last_chunk = chunks.last().unwrap();
630        assert_eq!(last_chunk.address, expected_addr);
631        assert_eq!(last_chunk.read_length + read_len, read_mem.read_length);
632    }
633
634    #[test]
635    fn test_write_mem_chunks() {
636        let data = vec![0; 128];
637        let write_mem = WriteMem::new(0, &data).unwrap();
638
639        let mut expected_addr = 0;
640        let mut sent_data_len = 0;
641
642        let chunks: Vec<_> = write_mem.chunks(24).unwrap().collect();
643
644        for (i, chunk) in chunks.iter().enumerate().take(chunks.len() - 1) {
645            assert_eq!(chunk.address, expected_addr);
646            expected_addr += u64::from(chunk.data_len);
647            sent_data_len += chunk.data_len;
648
649            assert_eq!(chunk.clone().finalize(i as u16).cmd_len(), 24);
650        }
651
652        let last_chunk = chunks.last().unwrap();
653        assert_eq!(last_chunk.address, expected_addr);
654        assert_eq!(last_chunk.data_len, data.len() as u16 - sent_data_len);
655    }
656}