1use crate::{
2 constants,
3 error::CrsfStreamError,
4 packets::{Packet, PacketAddress},
5};
6use crc::Crc;
7use num_enum::TryFromPrimitive;
8
9#[derive(Debug, Default, Ord, PartialOrd, Eq, PartialEq, Copy, Clone)]
10#[cfg_attr(feature = "defmt", derive(defmt::Format))]
11pub enum State {
12 #[default]
13 AwaitingSync,
14 AwaitingLenth,
15 Reading(usize),
16 AwaitingCrc,
17}
18
19#[derive(Debug)]
20pub struct CrsfParser {
21 buffer: [u8; constants::CRSF_MAX_PACKET_SIZE],
22 state: State,
23 position: usize,
24}
25
26const CRC8_DVB_S2: Crc<u8> = Crc::<u8>::new(&crc::CRC_8_DVB_S2);
27
28impl CrsfParser {
29 pub fn new() -> Self {
30 Self {
31 buffer: [0; constants::CRSF_MAX_PACKET_SIZE],
32 state: State::AwaitingSync,
33 position: 0,
34 }
35 }
36
37 pub fn push_byte_raw(
38 &mut self,
39 byte: u8,
40 ) -> Result<Option<RawCrsfPacket<'_>>, CrsfStreamError> {
41 match self.state {
42 State::AwaitingSync => {
43 if PacketAddress::try_from_primitive(byte).is_ok() {
44 self.position = 0;
45 self.buffer[self.position] = byte;
46 self.state = State::AwaitingLenth;
47 Ok(None)
48 } else {
49 self.state = State::AwaitingSync;
50 Err(CrsfStreamError::InvalidSync(byte))
51 }
52 }
53 State::AwaitingLenth => {
54 let n = byte as usize + 2;
55
56 if !(constants::CRSF_MIN_PACKET_SIZE..constants::CRSF_MAX_PACKET_SIZE).contains(&n)
57 {
58 self.reset();
59 return Err(CrsfStreamError::InvalidPacketLength(byte));
60 }
61 self.position = 1;
62 self.buffer[self.position] = byte;
63 self.state = State::Reading(n - 1);
64 Ok(None)
65 }
66 State::Reading(n) => {
67 self.position += 1;
68 self.buffer[self.position] = byte;
69 if self.position == n - 1 {
70 self.state = State::AwaitingCrc;
71 }
72 Ok(None)
73 }
74 State::AwaitingCrc => {
75 self.position += 1;
76 self.buffer[self.position] = byte;
77
78 let mut digest = CRC8_DVB_S2.digest();
79 digest.update(&self.buffer[2..self.position]);
80 let calculated_crc = digest.finalize();
81 let packet_crc = self.buffer[self.position];
82
83 if calculated_crc != packet_crc {
84 self.reset();
85 return Err(CrsfStreamError::InvalidCrc {
86 calculated_crc,
87 packet_crc,
88 });
89 }
90 let start = 0;
91 let end = self.position + 1;
92 self.reset();
93 let bytes = &self.buffer[start..end];
94 match RawCrsfPacket::new(bytes) {
95 None => Err(CrsfStreamError::InputBufferTooSmall),
96 Some(packet) => Ok(Some(packet)),
97 }
98 }
99 }
100 }
101
102 pub fn iter_packets<'a, 'b>(&'a mut self, buffer: &'b [u8]) -> PacketIterator<'a, 'b> {
103 PacketIterator {
104 parser: self,
105 buffer,
106 pos: 0,
107 }
108 }
109
110 pub fn push_byte(&mut self, byte: u8) -> Result<Option<Packet>, CrsfStreamError> {
111 match self.push_byte_raw(byte) {
112 Ok(Some(raw_packet)) => match Packet::parse(&raw_packet) {
113 Ok(packet) => Ok(Some(packet)),
114 Err(e) => Err(CrsfStreamError::ParsingError(e)),
115 },
116 Ok(None) => Ok(None),
117 Err(e) => Err(e),
118 }
119 }
120
121 pub fn reset(&mut self) {
122 self.position = 0;
123 self.state = State::AwaitingSync;
124 }
125}
126
127impl Default for CrsfParser {
128 fn default() -> Self {
129 Self::new()
130 }
131}
132
133#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
140#[cfg_attr(feature = "defmt", derive(defmt::Format))]
141pub struct RawCrsfPacket<'a> {
142 bytes: &'a [u8],
143}
144
145impl<'a> RawCrsfPacket<'a> {
146 pub fn new(bytes: &'a [u8]) -> Option<Self> {
151 if bytes.len() >= 4 {
152 Some(Self { bytes })
153 } else {
154 None
155 }
156 }
157
158 pub fn dst_addr(&self) -> u8 {
160 self.bytes[0]
161 }
162
163 pub fn raw_packet_type(&self) -> u8 {
165 self.bytes[2]
166 }
167
168 pub fn payload(&self) -> &[u8] {
172 &self.bytes[3..self.bytes.len() - 1]
173 }
174
175 #[expect(clippy::missing_panics_doc, reason = "infallible")]
177 pub fn crc(&self) -> u8 {
178 *self.bytes.last().expect("infallible due to length check")
179 }
180
181 pub fn len(&self) -> usize {
183 self.bytes.len()
184 }
185
186 pub fn is_empty(&self) -> bool {
190 self.bytes.is_empty()
191 }
192}
193
194pub struct PacketIterator<'a, 'b> {
195 parser: &'a mut CrsfParser,
196 buffer: &'b [u8],
197 pos: usize,
198}
199
200impl Iterator for PacketIterator<'_, '_> {
201 type Item = Result<Packet, CrsfStreamError>;
202
203 fn next(&mut self) -> Option<Self::Item> {
204 while self.pos < self.buffer.len() {
205 let byte = self.buffer[self.pos];
206 self.pos += 1;
207
208 match self.parser.push_byte(byte) {
209 Ok(Some(packet)) => return Some(Ok(packet)),
210 Ok(None) => (),
211 Err(err) => return Some(Err(err)),
212 }
213 }
214 None
215 }
216}
217
218#[cfg(test)]
219mod tests {
220 extern crate std;
221
222 use super::*;
223 use crate::packets::{
224 write_packet_to_buffer, CrsfPacket, LinkStatistics, PacketAddress, PacketType,
225 RcChannelsPacked,
226 };
227
228 #[test]
229 fn test_construction() {
230 let raw_bytes: [u8; 14] = [0xC8, 12, 0x14, 16, 19, 99, 151, 1, 2, 3, 8, 88, 148, 252];
231 let mut parser = CrsfParser::new();
232
233 for b in &raw_bytes[0..raw_bytes.len() - 1] {
234 let result = parser.push_byte_raw(*b);
235 assert!(matches!(result, Ok(None)));
236 }
237
238 let raw_packet_result = parser.push_byte_raw(raw_bytes[13]);
239 let raw_packet = raw_packet_result
240 .expect("Failed to get raw packet result")
241 .expect("Expected a complete raw packet, but got None");
242
243 assert_eq!(raw_packet.len(), raw_bytes.len());
244
245 assert_eq!(raw_packet.payload().len(), LinkStatistics::MIN_PAYLOAD_SIZE);
246 assert_eq!(
247 raw_packet.raw_packet_type(),
248 PacketType::LinkStatistics as u8
249 );
250
251 let data = &raw_packet.payload();
252 let ls = LinkStatistics::from_bytes(data).unwrap();
253 let p = Packet::parse(&raw_packet).unwrap();
254 assert_eq!(Packet::LinkStatistics(ls.clone()), p);
255
256 assert_eq!(ls.uplink_rssi_1, 16);
257 }
258
259 #[test]
260 fn test_parsing() {
261 let raw_bytes: [u8; 40] = [
262 0xC8, 12, 0x14, 16, 19, 99, 151, 1, 2, 3, 8, 88, 148, 252, 0xC8, 24, 0x16, 0xE0, 0x03,
263 0x1F, 0x58, 0xC0, 0x07, 0x16, 0xB0, 0x80, 0x05, 0x2C, 0x60, 0x01, 0x0B, 0xF8, 0xC0,
264 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 103,
265 ];
266 let mut parser = CrsfParser::new();
267 let results: std::vec::Vec<Result<Packet, CrsfStreamError>> =
268 parser.iter_packets(&raw_bytes).collect();
269
270 let expected = [
271 992, 992, 352, 992, 352, 352, 352, 352, 352, 352, 992, 992, 0, 0, 0, 0,
272 ];
273 assert_eq!(results.len(), 2);
274
275 assert!(results[0].is_ok());
276 assert!(results[1].is_ok());
277 assert_eq!(
278 Packet::RCChannels(RcChannelsPacked(expected)),
279 results[1].clone().ok().unwrap()
280 );
281 }
282
283 #[test]
284 fn test_raw_to_full_packet_conversion() {
285 let link_stats_packet = LinkStatistics {
286 uplink_rssi_1: 16,
287 uplink_rssi_2: 19,
288 uplink_link_quality: 99,
289 uplink_snr: 51 as i8,
290 active_antenna: 1,
291 rf_mode: 2,
292 uplink_tx_power: 3,
293 downlink_rssi: 8,
294 downlink_link_quality: 88,
295 downlink_snr: 48 as i8,
296 };
297
298 let mut buffer = [0u8; 64];
300 let bytes_written = write_packet_to_buffer(
301 &mut buffer,
302 PacketAddress::FlightController,
303 &link_stats_packet,
304 )
305 .unwrap();
306 let raw_bytes = &buffer[..bytes_written];
307
308 let mut parser = CrsfParser::new();
309
310 let mut raw_packet_result = Ok(None);
312 for &byte in raw_bytes {
313 raw_packet_result = parser.push_byte_raw(byte);
314 if let Ok(Some(_)) = &raw_packet_result {
315 break;
316 }
317 }
318 let raw_packet = raw_packet_result
319 .expect("Failed to get raw packet result")
320 .expect("Expected a complete raw packet, but got None");
321
322 let packet = Packet::parse(&raw_packet).expect("Failed to parse raw packet into a Packet");
323
324 assert!(matches!(packet, Packet::LinkStatistics(_)));
326 if let Packet::LinkStatistics(stats) = packet {
327 assert_eq!(stats, link_stats_packet)
328 }
329 }
330}