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