ti154/
frame.rs

1use crate::error::Error;
2use crate::types::{CommandType, MTExtendedHeaderStatus, MTSubsystem};
3use bytes::{Buf, BufMut};
4use num_traits::FromPrimitive;
5use std::io::{Cursor, Read};
6
7#[derive(Debug, Clone)]
8pub struct MTFrame {
9    pub header: MTHeader,
10    pub extended_header: Option<MTExtendedHeader>,
11    pub payload: Vec<u8>,
12}
13
14impl MTFrame {
15    pub fn try_decode(cursor: &mut Cursor<&[u8]>) -> Result<Self, Error> {
16        let header = MTHeader::try_decode(Read::by_ref(cursor))?;
17
18        let extended_header = if header.has_extension() {
19            Some(MTExtendedHeader::try_decode(Read::by_ref(cursor))?)
20        } else {
21            None
22        };
23
24        let mut payload = Vec::new();
25        cursor
26            .read_to_end(&mut payload)
27            .map_err(|_| Error::NotEnoughBytes)?;
28
29        Ok(MTFrame {
30            header,
31            extended_header,
32            payload,
33        })
34    }
35
36    pub fn encode_into(&self, buffer: &mut Vec<u8>) {
37        self.header.encode_into(buffer);
38
39        if let Some(ref extended_header) = self.extended_header {
40            extended_header.encode_into(buffer);
41        }
42
43        buffer.extend(self.payload.iter());
44    }
45
46    pub fn encode_to_uart_transport_frame(&self) -> Vec<u8> {
47        const START_OF_FRAME: u8 = 0xfe;
48        let mut buffer = Vec::new();
49        buffer.put_u8(START_OF_FRAME);
50        self.encode_into(&mut buffer);
51        let fcs = Self::compute_frame_check_sequence(&buffer[1..]);
52        buffer.put_u8(fcs);
53        buffer
54    }
55
56    pub fn compute_frame_check_sequence(mt_frame_bytes: &[u8]) -> u8 {
57        mt_frame_bytes.iter().fold(0, |acc, x| acc ^ x)
58    }
59}
60
61#[derive(Debug, Clone)]
62pub struct MTHeader {
63    pub length: u8,
64    pub command: CommandCode,
65}
66
67impl MTHeader {
68    pub fn size() -> usize {
69        return 3;
70    }
71
72    pub fn has_extension(&self) -> bool {
73        self.command.is_extended
74    }
75
76    pub fn try_decode(cursor: &mut Cursor<&[u8]>) -> Result<Self, Error> {
77        let length = cursor.get_u8();
78        let command = CommandCode::try_decode(cursor)?;
79        Ok(MTHeader { length, command })
80    }
81
82    pub fn encode_into(&self, buffer: &mut Vec<u8>) {
83        buffer.put_u8(self.length);
84        self.command.encode_into(buffer);
85    }
86}
87
88#[derive(Debug, PartialEq, Clone)]
89pub struct CommandCode {
90    pub is_extended: bool,
91    pub cmd_type: CommandType,
92    pub subsystem: MTSubsystem,
93    pub id: u8,
94}
95
96impl CommandCode {
97    pub fn try_decode(cursor: &mut Cursor<&[u8]>) -> Result<Self, Error> {
98        let type_and_subsystem = cursor.get_u8();
99        let id = cursor.get_u8();
100
101        let is_extended = (type_and_subsystem & 0x80) != 0;
102
103        let cmd_type = 0x03 & (type_and_subsystem >> 5);
104        let cmd_type =
105            FromPrimitive::from_u8(cmd_type).ok_or(Error::InvalidCommandType(cmd_type))?;
106
107        let subsystem = type_and_subsystem & 0x1F;
108        let subsystem =
109            FromPrimitive::from_u8(subsystem).ok_or(Error::InvalidSubsystem(subsystem))?;
110
111        Ok(CommandCode {
112            is_extended,
113            cmd_type,
114            subsystem,
115            id,
116        })
117    }
118
119    pub fn encode_into(&self, buffer: &mut Vec<u8>) {
120        let type_and_subsystem = {
121            let value = ((self.cmd_type as u8) << 5) | (self.subsystem as u8);
122            if self.is_extended {
123                0x80 | value
124            } else {
125                value
126            }
127        };
128        buffer.put_u8(type_and_subsystem);
129        buffer.put_u8(self.id);
130    }
131}
132
133#[derive(Debug, Clone)]
134pub enum MTExtendedHeader {
135    V1 {
136        stack_id: u8,
137    },
138    V2 {
139        stack_id: u8,
140        block: u8,
141        packet_length: u16,
142    },
143    V3 {
144        stack_id: u8,
145        block: u8,
146        status: MTExtendedHeaderStatus,
147    },
148    V4 {
149        stack_id: u8,
150        block: u8,
151        status: MTExtendedHeaderStatus,
152    },
153}
154
155impl MTExtendedHeader {
156    pub fn try_decode(cursor: &mut Cursor<&[u8]>) -> Result<Self, Error> {
157        let version_and_stack_id = cursor.get_u8();
158        let version = (version_and_stack_id & 0xf8) >> 3;
159        let stack_id = version_and_stack_id & 0x07;
160
161        if version == 1 {
162            return Ok(MTExtendedHeader::V1 { stack_id });
163        }
164
165        let block = cursor.get_u8();
166
167        if version == 2 {
168            let packet_length = cursor.get_u16_le();
169            return Ok(MTExtendedHeader::V2 {
170                stack_id,
171                block,
172                packet_length,
173            });
174        }
175
176        if version == 3 || version == 4 {
177            let status = MTExtendedHeaderStatus::try_decode(cursor)?;
178
179            if version == 3 {
180                return Ok(MTExtendedHeader::V3 {
181                    stack_id,
182                    block,
183                    status,
184                });
185            } else {
186                return Ok(MTExtendedHeader::V4 {
187                    stack_id,
188                    block,
189                    status,
190                });
191            }
192        }
193
194        Err(Error::NotImplemented)
195    }
196
197    pub fn encode_into(&self, buffer: &mut Vec<u8>) {
198        match self {
199            MTExtendedHeader::V1 { stack_id } => {
200                let version_and_stack_id = (1 << 3) | stack_id;
201                buffer.put_u8(version_and_stack_id);
202            }
203            MTExtendedHeader::V2 {
204                stack_id,
205                block,
206                packet_length,
207            } => {
208                let version_and_stack_id = (2 << 3) | stack_id;
209                buffer.put_u8(version_and_stack_id);
210                buffer.put_u8(*block);
211                buffer.put_u16_le(*packet_length);
212            }
213            MTExtendedHeader::V3 {
214                stack_id,
215                block,
216                status,
217            } => {
218                let version_and_stack_id = (3 << 3) | stack_id;
219                buffer.put_u8(version_and_stack_id);
220                buffer.put_u8(*block);
221                status.encode_into(buffer);
222            }
223            MTExtendedHeader::V4 {
224                stack_id,
225                block,
226                status,
227            } => {
228                let version_and_stack_id = (4 << 3) | stack_id;
229                buffer.put_u8(version_and_stack_id);
230                buffer.put_u8(*block);
231                status.encode_into(buffer);
232            }
233        }
234    }
235}