ebds/flash_download/
message_8bit.rs

1use crate::std;
2use std::fmt;
3
4use crate::{
5    impl_default, impl_message_ops,
6    len::{
7        FLASH_DATA_PACKET, FLASH_DATA_PACKET_64, FLASH_DOWNLOAD_MESSAGE_8BIT_32,
8        FLASH_DOWNLOAD_MESSAGE_8BIT_64,
9    },
10    MessageOps, MessageType,
11};
12
13use super::FlashDownloadMessage;
14
15pub mod index {
16    pub const PACKET0: usize = 3;
17    pub const PACKET1: usize = 4;
18    pub const DATA0: usize = 5;
19    pub const DATA31: usize = 36;
20    pub const DATA63: usize = 68;
21}
22
23/// Flash Download Message - 8-Bit protocol (Fast Serial Algorithm) (64-byte packet)
24///
25/// Starting at the beginning of the file, the host sends 64 byte blocks of data to the device. Downloading is
26/// completed through the Download Data command shown below. The full 8-bits can be used for packet
27/// numbers and data packets.
28///
29/// **Warning** The file is required to be a multiple of 32 bytes long therefore it is possible for the final
30/// packet to only contain the remaining 32 data bytes. Do not pad the message with empty values.
31///
32/// The Flash Download Message (8-bit, 64-byte packet) is formatted as follows:
33///
34/// | Name  | STX  | LEN  | CTRL | Packet #0 | Packet #1 | Data 0 | ...  | Data 63 | ETX  | CHK |
35/// |:------|:----:|:----:|:----:|:---------:|:---------:|:------:|:----:|:-------:|:----:|:---:|
36/// | Byte  | 0    | 1    | 2    | 3         | 4         | 5      | ...  | 68      | 69   | 70  |
37/// | Value | 0x02 | 0x47 | 0x5n | 0xnn      | 0xnn      | 0xnn   | 0xnn | 0xnn    | 0x03 | zz  |
38///
39/// **Note**: the 16-bit packet numbers are stored in little-endian format (least-significant byte first)
40#[repr(C)]
41#[derive(Clone, Copy, Debug, PartialEq)]
42pub struct FlashDownloadMessage8bit_64 {
43    buf: [u8; FLASH_DOWNLOAD_MESSAGE_8BIT_64],
44}
45
46impl FlashDownloadMessage8bit_64 {
47    pub fn new() -> Self {
48        let mut msg = Self {
49            buf: [0u8; FLASH_DOWNLOAD_MESSAGE_8BIT_64],
50        };
51
52        msg.init();
53        msg.set_message_type(MessageType::FirmwareDownload);
54
55        msg
56    }
57}
58
59impl_default!(FlashDownloadMessage8bit_64);
60impl_message_ops!(FlashDownloadMessage8bit_64);
61
62impl FlashDownloadMessage<FLASH_DATA_PACKET_64> for FlashDownloadMessage8bit_64 {
63    fn packet_number(&self) -> u16 {
64        u16::from_le_bytes([self.buf[index::PACKET0], self.buf[index::PACKET1]])
65    }
66
67    fn set_packet_number(&mut self, n: u16) {
68        self.buf[index::PACKET0..=index::PACKET1].copy_from_slice(n.to_le_bytes().as_ref());
69    }
70
71    fn increment_packet_number(&mut self) -> u16 {
72        // FIXME: the desired behavior of an increment past the max is unclear.
73        //
74        // C behavior is to overflow, restarting at 0, but it isn't obvious that's what CPI
75        // intends.
76        //
77        // FWIW their firmware files all appear to be below the limit.
78        let packet_number = self.packet_number().overflowing_add(1).0;
79        self.set_packet_number(packet_number);
80        packet_number
81    }
82
83    fn data(&self) -> [u8; FLASH_DATA_PACKET_64] {
84        // The unwrap is safe here, and can never panic because the slice is guaranteed to be the
85        // correct length.
86        self.buf[index::DATA0..=index::DATA63].try_into().unwrap()
87    }
88
89    fn data_ref(&self) -> &[u8] {
90        self.buf[index::DATA0..=index::DATA63].as_ref()
91    }
92
93    fn set_data(&mut self, data: &[u8]) {
94        assert_eq!(data.len(), FLASH_DATA_PACKET_64);
95
96        self.buf[index::DATA0..=index::DATA63].copy_from_slice(data);
97    }
98}
99
100impl fmt::Display for FlashDownloadMessage8bit_64 {
101    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102        write!(
103            f,
104            "AckNak: {}, DeviceType: {}, MessageType: {}, PacketNumber: {}, Data: {:x?}",
105            self.acknak(),
106            self.device_type(),
107            self.message_type(),
108            self.packet_number(),
109            self.data(),
110        )
111    }
112}
113
114/// Flash Download Message - 8-Bit protocol (Fast Serial Algorithm) (32-byte packet)
115///
116/// Starting at the beginning of the file, the host sends 64 byte blocks of data to the device. Downloading is
117/// completed through the Download Data command shown below. The full 8-bits can be used for packet
118/// numbers and data packets.
119///
120/// **Warning** The file is required to be a multiple of 32 bytes long therefore it is possible for the final
121/// packet to only contain the remaining 32 data bytes. Do not pad the message with empty values.
122///
123/// The Flash Download Message (8-bit, 32-byte packet) is formatted as follows:
124///
125/// | Name  | STX  | LEN  | CTRL | Packet #0 | Packet #1 | Data 0 | ...  | Data 31 | ETX  | CHK |
126/// |:------|:----:|:----:|:----:|:---------:|:---------:|:------:|:----:|:-------:|:----:|:---:|
127/// | Byte  | 0    | 1    | 2    | 3         | 4         | 5      | ...  | 36      | 37   | 38  |
128/// | Value | 0x02 | 0x27 | 0x5n | 0xnn      | 0xnn      | 0xnn   | 0xnn | 0xnn    | 0x03 | zz  |
129///
130/// **Note**: the 16-bit packet numbers are stored in little-endian format (least-significant byte first)
131#[repr(C)]
132#[derive(Clone, Copy, Debug, PartialEq)]
133pub struct FlashDownloadMessage8bit_32 {
134    buf: [u8; FLASH_DOWNLOAD_MESSAGE_8BIT_32],
135}
136
137impl FlashDownloadMessage8bit_32 {
138    pub fn new() -> Self {
139        let mut msg = Self {
140            buf: [0u8; FLASH_DOWNLOAD_MESSAGE_8BIT_32],
141        };
142
143        msg.init();
144        msg.set_message_type(MessageType::FirmwareDownload);
145
146        msg
147    }
148}
149
150impl_default!(FlashDownloadMessage8bit_32);
151impl_message_ops!(FlashDownloadMessage8bit_32);
152
153impl FlashDownloadMessage<FLASH_DATA_PACKET> for FlashDownloadMessage8bit_32 {
154    fn packet_number(&self) -> u16 {
155        u16::from_le_bytes([self.buf[index::PACKET0], self.buf[index::PACKET1]])
156    }
157
158    fn set_packet_number(&mut self, n: u16) {
159        self.buf[index::PACKET0..=index::PACKET1].copy_from_slice(n.to_le_bytes().as_ref());
160    }
161
162    fn increment_packet_number(&mut self) -> u16 {
163        // FIXME: the desired behavior of an increment past the max is unclear.
164        //
165        // C behavior is to overflow, restarting at 0, but it isn't obvious that's what CPI
166        // intends.
167        //
168        // FWIW their firmware files all appear to be below the limit.
169        let packet_number = self.packet_number().overflowing_add(1).0;
170        self.set_packet_number(packet_number);
171        packet_number
172    }
173
174    fn data(&self) -> [u8; FLASH_DATA_PACKET] {
175        // The unwrap is safe here, and can never panic because the slice is guaranteed to be the
176        // correct length.
177        self.buf[index::DATA0..=index::DATA31].try_into().unwrap()
178    }
179
180    fn data_ref(&self) -> &[u8] {
181        self.buf[index::DATA0..=index::DATA31].as_ref()
182    }
183
184    fn set_data(&mut self, data: &[u8]) {
185        assert_eq!(data.len(), FLASH_DATA_PACKET);
186
187        self.buf[index::DATA0..=index::DATA31].copy_from_slice(data);
188    }
189}
190
191impl fmt::Display for FlashDownloadMessage8bit_32 {
192    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
193        write!(
194            f,
195            "AckNak: {}, DeviceType: {}, MessageType: {}, PacketNumber: {}, Data: {:x?}",
196            self.acknak(),
197            self.device_type(),
198            self.message_type(),
199            self.packet_number(),
200            self.data(),
201        )
202    }
203}
204
205#[cfg(test)]
206mod tests {
207    use super::*;
208    use crate::Result;
209
210    #[test]
211    #[rustfmt::skip]
212    fn flash_download_message_8bit_64_from_buf() -> Result<()> {
213        let msg_bytes = [
214            // STX | LEN | Message Type
215            0x02, 0x47, 0x50,
216            // Packet number (little-endian)
217            0x34, 0x12,
218            // Data
219            0x54, 0x01, 0x03, 0x04, 0x00, 0xa0, 0x00, 0x20, 0x00, 0x7f, 0x5a, 0x01, 0xc0, 0x1f, 0x00, 0x00,
220            0x59, 0xae, 0x00, 0x20, 0x03, 0x00, 0x07, 0x32, 0x38, 0x36, 0x31, 0x30, 0x31, 0x31, 0x30, 0x33,
221            0x54, 0x01, 0x03, 0x04, 0x00, 0xa0, 0x00, 0x20, 0x00, 0x7f, 0x5a, 0x01, 0xc0, 0x1f, 0x00, 0x00,
222            0x59, 0xae, 0x00, 0x20, 0x03, 0x00, 0x07, 0x32, 0x38, 0x36, 0x31, 0x30, 0x31, 0x31, 0x03, 0x33,
223            // ETX | Checksum
224            0x03, 0x02,
225        ];
226
227        let mut msg = FlashDownloadMessage8bit_64::new();
228        msg.from_buf(msg_bytes.as_ref())?;
229
230        assert_eq!(msg.message_type(), MessageType::FirmwareDownload);
231        assert_eq!(msg.packet_number(), 0x1234);
232        assert_eq!(msg.data_ref(), msg_bytes[index::DATA0..=index::DATA63].as_ref());
233        assert_eq!(msg.data().as_ref(), msg_bytes[index::DATA0..=index::DATA63].as_ref());
234
235        assert_eq!(msg.increment_packet_number(), 0x1235);
236        assert_eq!(msg.packet_number(), 0x1235);
237
238        Ok(())
239    }
240
241    #[test]
242    #[rustfmt::skip]
243    fn flash_download_message_8bit_32_from_buf() -> Result<()> {
244        let msg_bytes = [
245            // STX | LEN | Message Type
246            0x02, 0x27, 0x50,
247            // Packet number (little-endian)
248            0x34, 0x12,
249            // Data
250            0x54, 0x01, 0x03, 0x04, 0x00, 0xa0, 0x00, 0x20, 0x00, 0x7f, 0x5a, 0x01, 0xc0, 0x1f, 0x00, 0x00,
251            0x59, 0xae, 0x00, 0x20, 0x03, 0x00, 0x07, 0x32, 0x38, 0x36, 0x31, 0x30, 0x31, 0x31, 0x30, 0x33,
252            // ETX | Checksum
253            0x03, 0x95,
254        ];
255
256        let mut msg = FlashDownloadMessage8bit_32::new();
257        msg.from_buf(msg_bytes.as_ref())?;
258
259        assert_eq!(msg.message_type(), MessageType::FirmwareDownload);
260        assert_eq!(msg.packet_number(), 0x1234);
261        assert_eq!(msg.data_ref(), msg_bytes[index::DATA0..=index::DATA31].as_ref());
262        assert_eq!(msg.data().as_ref(), msg_bytes[index::DATA0..=index::DATA31].as_ref());
263
264        assert_eq!(msg.increment_packet_number(), 0x1235);
265        assert_eq!(msg.packet_number(), 0x1235);
266
267        Ok(())
268    }
269}