1
1
use prelude:: v1:: * ;
2
+ use crc_any:: CRCu8 ;
3
+
2
4
3
5
/// Packet parsing error
4
6
#[ derive( Copy , Clone , Debug , PartialEq ) ]
@@ -38,7 +40,7 @@ impl MspPacketDirection {
38
40
#[ derive( Debug , Clone , PartialEq ) ]
39
41
/// A decoded MSP packet, with a command code, direction and payload
40
42
pub struct MspPacket < ' a > {
41
- pub cmd : u8 ,
43
+ pub cmd : u16 ,
42
44
pub direction : MspPacketDirection ,
43
45
pub data : Cow < ' a , [ u8 ] >
44
46
}
@@ -48,33 +50,48 @@ enum MspParserState {
48
50
Header1 ,
49
51
Header2 ,
50
52
Direction ,
53
+ FlagV2 ,
51
54
DataLength ,
55
+ DataLengthV2 ,
52
56
Command ,
57
+ CommandV2 ,
53
58
Data ,
54
- Crc
59
+ DataV2 ,
60
+ Crc ,
61
+ CrcV2 ,
62
+ }
63
+
64
+ #[ derive( Copy , Clone , PartialEq , Debug ) ]
65
+ enum MSPVersion {
66
+ V1 ,
67
+ V2 ,
55
68
}
56
69
57
70
#[ derive( Debug ) ]
58
71
/// Parser that can find packets from a raw byte stream
59
72
pub struct MspParser {
60
73
state : MspParserState ,
74
+ packet_version : MSPVersion ,
61
75
packet_direction : MspPacketDirection ,
62
- packet_cmd : u8 ,
63
- packet_data_length_remaining : usize ,
76
+ packet_cmd : u16 ,
77
+ packet_data_length_remaining : u16 ,
64
78
packet_data : Vec < u8 > ,
65
- packet_crc : u8
79
+ packet_crc : u8 ,
80
+ packet_crc_v2 : CRCu8 ,
66
81
}
67
82
68
83
impl MspParser {
69
84
/// Create a new parser
70
85
pub fn new ( ) -> MspParser {
71
- MspParser {
86
+ Self {
72
87
state : MspParserState :: Header1 ,
88
+ packet_version : MSPVersion :: V1 ,
73
89
packet_direction : MspPacketDirection :: ToFlightController ,
74
90
packet_data_length_remaining : 0 ,
75
91
packet_cmd : 0 ,
76
92
packet_data : Vec :: new ( ) ,
77
- packet_crc : 0
93
+ packet_crc : 0 ,
94
+ packet_crc_v2 : CRCu8 :: crc8dvb_s2 ( ) ,
78
95
}
79
96
}
80
97
@@ -96,11 +113,16 @@ impl MspParser {
96
113
} ,
97
114
98
115
MspParserState :: Header2 => {
99
- if input == ( 'M' as u8 ) {
100
- self . state = MspParserState :: Direction ;
101
- } else {
102
- self . reset ( ) ;
103
- }
116
+ self . packet_version = match input as char {
117
+ 'M' => MSPVersion :: V1 ,
118
+ 'X' => MSPVersion :: V2 ,
119
+ _=> {
120
+ self . reset ( ) ;
121
+ return Ok ( None ) ;
122
+ } ,
123
+ } ;
124
+
125
+ self . state = MspParserState :: Direction ;
104
126
} ,
105
127
106
128
MspParserState :: Direction => {
@@ -114,20 +136,71 @@ impl MspParser {
114
136
}
115
137
}
116
138
117
- self . state = MspParserState :: DataLength ;
139
+ self . state = match self . packet_version {
140
+ MSPVersion :: V1 => MspParserState :: DataLength ,
141
+ MSPVersion :: V2 => MspParserState :: FlagV2 ,
142
+ } ;
118
143
} ,
119
144
120
- MspParserState :: DataLength => {
145
+ MspParserState :: FlagV2 => {
146
+ // uint8, flag, usage to be defined (set to zero)
147
+ self . state = MspParserState :: CommandV2 ;
148
+ self . packet_data = Vec :: with_capacity ( 2 ) ;
149
+ self . packet_crc_v2 . digest ( & [ input] ) ;
150
+ } ,
151
+
152
+ MspParserState :: CommandV2 => {
153
+ self . packet_data . push ( input) ;
154
+
155
+ if self . packet_data . len ( ) == 2 {
156
+ let mut s = [ 0 ; 2 ] ;
157
+ s. copy_from_slice ( & self . packet_data ) ;
158
+ self . packet_cmd = u16:: from_le_bytes ( s) ;
159
+
160
+ self . packet_data . clear ( ) ;
161
+ self . state = MspParserState :: DataLengthV2 ;
162
+ }
163
+
164
+ self . packet_crc_v2 . digest ( & [ input] ) ;
165
+ } ,
166
+
167
+ MspParserState :: DataLengthV2 => {
168
+ self . packet_data . push ( input) ;
121
169
122
- self . packet_data_length_remaining = input as usize ;
170
+ if self . packet_data . len ( ) == 2 {
171
+ let mut s = [ 0 ; 2 ] ;
172
+ s. copy_from_slice ( & self . packet_data ) ;
173
+ self . packet_data_length_remaining = u16:: from_le_bytes ( s) ;
174
+ self . packet_data = Vec :: with_capacity ( self . packet_data_length_remaining as usize ) ;
175
+
176
+ self . state = MspParserState :: DataV2 ;
177
+ }
178
+
179
+ self . packet_crc_v2 . digest ( & [ input] ) ;
180
+ } ,
181
+
182
+ MspParserState :: DataV2 => {
183
+ self . packet_data . push ( input) ;
184
+ self . packet_data_length_remaining -= 1 ;
185
+
186
+
187
+ if self . packet_data_length_remaining == 0 {
188
+ self . state = MspParserState :: CrcV2 ;
189
+ }
190
+
191
+ self . packet_crc_v2 . digest ( & [ input] ) ;
192
+ } ,
193
+
194
+ MspParserState :: DataLength => {
195
+ self . packet_data_length_remaining = input as u16 ;
123
196
self . state = MspParserState :: Command ;
124
197
self . packet_crc ^= input;
125
198
self . packet_data = Vec :: with_capacity ( input as usize ) ;
126
199
} ,
127
200
128
201
MspParserState :: Command => {
129
202
130
- self . packet_cmd = input;
203
+ self . packet_cmd = input as u16 ;
131
204
132
205
if self . packet_data_length_remaining == 0 {
133
206
self . state = MspParserState :: Crc ;
@@ -152,8 +225,12 @@ impl MspParser {
152
225
153
226
} ,
154
227
155
- MspParserState :: Crc => {
228
+ MspParserState :: CrcV2 => {
229
+ self . packet_crc = self . packet_crc_v2 . get_crc ( ) ;
230
+ self . state = MspParserState :: Crc ;
231
+ } ,
156
232
233
+ MspParserState :: Crc => {
157
234
let packet_crc = self . packet_crc ;
158
235
if input != packet_crc {
159
236
self . reset ( ) ;
@@ -186,6 +263,7 @@ impl MspParser {
186
263
self . packet_cmd = 0 ;
187
264
self . packet_data . clear ( ) ;
188
265
self . packet_crc = 0 ;
266
+ self . packet_crc_v2 . reset ( ) ;
189
267
}
190
268
}
191
269
@@ -195,6 +273,11 @@ impl<'a> MspPacket<'a> {
195
273
6 + self . data . len ( )
196
274
}
197
275
276
+ /// Number of bytes that this packet requires to be packed
277
+ pub fn packet_size_bytes_v2 ( & self ) -> usize {
278
+ 9 + self . data . len ( )
279
+ }
280
+
198
281
/// Serialize to network bytes
199
282
pub fn serialize ( & self , output : & mut [ u8 ] ) -> Result < ( ) , MspPacketParseError > {
200
283
let l = output. len ( ) ;
@@ -207,7 +290,7 @@ impl<'a> MspPacket<'a> {
207
290
output[ 1 ] = 'M' as u8 ;
208
291
output[ 2 ] = self . direction . to_byte ( ) ;
209
292
output[ 3 ] = self . data . len ( ) as u8 ;
210
- output[ 4 ] = self . cmd ;
293
+ output[ 4 ] = self . cmd as u8 ;
211
294
212
295
213
296
output[ 5 ..l - 1 ] . copy_from_slice ( & self . data ) ;
@@ -220,6 +303,30 @@ impl<'a> MspPacket<'a> {
220
303
221
304
Ok ( ( ) )
222
305
}
306
+
307
+ /// Serialize to network bytes
308
+ pub fn serialize_v2 ( & self , output : & mut [ u8 ] ) -> Result < ( ) , MspPacketParseError > {
309
+ let l = output. len ( ) ;
310
+
311
+ if l != self . packet_size_bytes_v2 ( ) {
312
+ return Err ( MspPacketParseError :: OutputBufferSizeMismatch ) ;
313
+ }
314
+
315
+ output[ 0 ] = '$' as u8 ;
316
+ output[ 1 ] = 'X' as u8 ;
317
+ output[ 2 ] = self . direction . to_byte ( ) ;
318
+ output[ 3 ] = 0 ;
319
+ output[ 4 ..6 ] . copy_from_slice ( & self . cmd . to_le_bytes ( ) ) ;
320
+ output[ 6 ..8 ] . copy_from_slice ( & ( self . data . len ( ) as u16 ) . to_le_bytes ( ) ) ;
321
+
322
+ output[ 8 ..l - 1 ] . copy_from_slice ( & self . data ) ;
323
+
324
+ let mut crc = CRCu8 :: crc8dvb_s2 ( ) ;
325
+ crc. digest ( & output[ 3 ..l - 1 ] ) ;
326
+ output[ l - 1 ] = CRCu8 :: crc8dvb_s2 ( ) . get_crc ( ) ;
327
+
328
+ Ok ( ( ) )
329
+ }
223
330
}
224
331
225
332
@@ -301,4 +408,4 @@ fn test_roundtrip() {
301
408
} ;
302
409
roundtrip ( & packet) ;
303
410
}
304
- }
411
+ }
0 commit comments