]>
code.octet-stream.net Git - m17rt/blob - m17core/src/kiss.rs
1 // Note FEND and FESC both have the top two bits set. In the header byte this corresponds
2 // to high port numbers which are never used by M17 so we needn't bother (un)escaping it.
6 const TFEND
: u8 = 0xDC;
7 const TFESC
: u8 = 0xDD;
9 pub const PORT_PACKET_BASIC
: u8 = 0;
10 pub const PORT_PACKET_FULL
: u8 = 1;
11 pub const PORT_STREAM
: u8 = 2;
13 /// Maximum theoretical frame size for any valid M17 KISS frame.
15 /// In M17 Full Packet Mode a 30-byte LSF is merged with a packet which may be up to
16 /// 825 bytes in length. Supposing an (impossible) worst case that every byte is FEND
17 /// or FESC, 1710 bytes is the maximum expected payload. With a FEND at each end and
18 /// the KISS frame header byte we get 1713.
19 pub const MAX_FRAME_LEN
: usize = 1713;
21 /// Holder for any valid M17 KISS frame.
23 /// For efficiency, `data` and `len` are exposed directly and received KISS data may
24 /// be streamed directly into a pre-allocated `KissFrame`.
25 pub struct KissFrame
{
26 pub data
: [u8; MAX_FRAME_LEN
],
31 /// Request to transmit a data packet (basic mode).
33 /// A raw payload up to 822 bytes can be provided. The TNC will mark it as Raw format
34 /// and automatically calculate the checksum. If required it will also chunk the packet
35 /// into individual frames and transmit them sequentially.
36 pub fn new_basic_packet(payload
: &[u8]) -> Result
<Self, KissError
> {
37 // M17 packet payloads can be up to 825 bytes in length
38 // Type prefix (RAW = 0x00) occupies the first byte
39 // Last 2 bytes are checksum
40 if payload
.len() > 822 {
41 return Err(KissError
::PayloadTooBig
);
43 let mut data
= [0u8; MAX_FRAME_LEN
];
45 push(&mut data
, &mut i
, FEND
);
49 kiss_header(PORT_PACKET_BASIC
, KissCommand
::DataFrame
.proto_value()),
52 i
+= escape(payload
, &mut data
[i
..]);
53 push(&mut data
, &mut i
, FEND
);
55 Ok(KissFrame
{ data
, len
: i
})
58 /// Request to transmit a data packet (full mode).
60 /// Sender must provide a 30-byte LSF and a full packet payload (up to 825 bytes)
61 /// that will be combined into the frame. The packet payload must include the type
62 /// code prefix and the CRC, both of which would have been calculated by the TNC if
63 /// it was basic mode.
64 pub fn new_full_packet(lsf
: &[u8], packet
: &[u8]) -> Result
<Self, KissError
> {
66 return Err(KissError
::LsfWrongSize
);
68 if packet
.len() > 825 {
69 return Err(KissError
::PayloadTooBig
);
71 let mut data
= [0u8; MAX_FRAME_LEN
];
73 push(&mut data
, &mut i
, FEND
);
77 kiss_header(PORT_PACKET_FULL
, KissCommand
::DataFrame
.proto_value()),
79 i
+= escape(lsf
, &mut data
[i
..]);
80 i
+= escape(packet
, &mut data
[i
..]);
81 push(&mut data
, &mut i
, FEND
);
83 Ok(KissFrame
{ data
, len
: i
})
86 /// Request to begin a stream data transfer (e.g. voice).
88 /// An LSF payload of exactly 30 bytes must be provided.
90 /// This must be followed by at least one stream data payload, ending with one that
91 /// has the end of stream (EOS) bit set.
92 pub fn new_stream_setup(lsf
: &[u8]) -> Result
<Self, KissError
> {
94 return Err(KissError
::LsfWrongSize
);
96 let mut data
= [0u8; MAX_FRAME_LEN
];
98 push(&mut data
, &mut i
, FEND
);
102 kiss_header(PORT_STREAM
, KissCommand
::DataFrame
.proto_value()),
104 i
+= escape(lsf
, &mut data
[i
..]);
105 push(&mut data
, &mut i
, FEND
);
107 Ok(KissFrame
{ data
, len
: i
})
110 /// Transmit a segment of data in a stream transfer (e.g. voice).
112 /// A data payload of 26 bytes including metadata must be provided. This must follow
113 /// exactly the prescribed format (H.5.2 in the spec). The TNC will be watching for
114 /// the EOS flag to know that this transmission has ended.
115 pub fn new_stream_data(stream_data
: &[u8]) -> Result
<Self, KissError
> {
116 if stream_data
.len() != 26 {
117 return Err(KissError
::StreamDataWrongSize
);
119 let mut data
= [0u8; MAX_FRAME_LEN
];
121 push(&mut data
, &mut i
, FEND
);
125 kiss_header(PORT_STREAM
, KissCommand
::DataFrame
.proto_value()),
127 i
+= escape(stream_data
, &mut data
[i
..]);
128 push(&mut data
, &mut i
, FEND
);
130 Ok(KissFrame
{ data
, len
: i
})
133 /// Request to set the TxDelay
134 pub fn new_set_tx_delay(port
: u8, units
: u8) -> Self {
135 let mut data
= [0u8; MAX_FRAME_LEN
];
137 push(&mut data
, &mut i
, FEND
);
141 kiss_header(port
, KissCommand
::TxDelay
.proto_value()),
143 push(&mut data
, &mut i
, units
);
144 push(&mut data
, &mut i
, FEND
);
146 KissFrame
{ data
, len
: i
}
149 /// Request to set the persistence parameter P
150 pub fn new_set_p(port
: u8, units
: u8) -> Self {
151 let mut data
= [0u8; MAX_FRAME_LEN
];
153 push(&mut data
, &mut i
, FEND
);
157 kiss_header(port
, KissCommand
::P
.proto_value()),
159 push(&mut data
, &mut i
, units
);
160 push(&mut data
, &mut i
, FEND
);
162 KissFrame
{ data
, len
: i
}
165 /// Request to set full duplex or not
166 pub fn set_full_duplex(port
: u8, full_duplex
: bool
) -> Self {
167 let mut data
= [0u8; MAX_FRAME_LEN
];
169 push(&mut data
, &mut i
, FEND
);
173 kiss_header(port
, KissCommand
::FullDuplex
.proto_value()),
175 push(&mut data
, &mut i
, if full_duplex
{ 1 } else { 0 });
176 push(&mut data
, &mut i
, FEND
);
178 KissFrame
{ data
, len
: i
}
181 /// Return this frame's KISS command type.
182 pub fn command(&self) -> Result
<KissCommand
, KissError
> {
183 KissCommand
::from_proto(self.header_byte()?
& 0x0f)
186 /// Return the KISS port to which this frame relates. Should be 0, 1 or 2.
187 pub fn port(&self) -> Result
<u8, KissError
> {
188 Ok(self.header_byte()?
>> 4)
191 /// Payload part of the frame between the header byte and the trailing FEND, unescaped.
192 pub fn decode_payload(&self, out
: &mut [u8]) -> Result
<usize, KissError
> {
197 .skip_while(|(_
, b
)| **b
== FEND
)
200 .ok_or(KissError
::MalformedKissFrame
)?
202 let end
= self.data
[start
..]
205 .skip_while(|(_
, b
)| **b
!= FEND
)
207 .ok_or(KissError
::MalformedKissFrame
)?
210 Ok(unescape(&self.data
[start
..end
], out
))
213 /// Borrow the frame as a slice
214 pub fn as_bytes(&self) -> &[u8] {
215 &self.data
[..self.len
]
218 /// Return the header byte of the KISS frame, skipping over 0 or more prepended FENDs.
219 fn header_byte(&self) -> Result
<u8, KissError
> {
223 .skip_while(|b
| **b
== FEND
)
226 .ok_or(KissError
::MalformedKissFrame
)?
)
230 fn kiss_header(port
: u8, command
: u8) -> u8 {
231 (port
<< 4) | (command
& 0x0f)
234 fn push(data
: &mut [u8], idx
: &mut usize, value
: u8) {
239 pub enum KissCommand
{
247 fn from_proto(value
: u8) -> Result
<Self, KissError
> {
249 0 => KissCommand
::DataFrame
,
250 1 => KissCommand
::TxDelay
,
252 5 => KissCommand
::FullDuplex
,
253 _
=> return Err(KissError
::UnsupportedKissCommand
),
257 fn proto_value(&self) -> u8 {
259 KissCommand
::DataFrame
=> 0,
260 KissCommand
::TxDelay
=> 1,
262 KissCommand
::FullDuplex
=> 5,
270 UnsupportedKissCommand
,
276 fn escape(src
: &[u8], dst
: &mut [u8]) -> usize {
279 while i
< src
.len() && j
< dst
.len() {
284 } else if src
[i
] == FESC
{
297 fn unescape(src
: &[u8], dst
: &mut [u8]) -> usize {
300 while i
< src
.len() && j
< dst
.len() {
302 if i
== src
.len() - 1 {
308 } else if src
[i
] == TFESC
{
326 let mut buf
= [0u8; 1024];
328 let src
= [0, 1, 2, 3, 4, 5];
329 let n
= escape(&src
, &mut buf
);
331 assert_eq
!(&buf
[0..6], src
);
333 let src
= [0, 1, TFESC
, 3, TFEND
, 5];
334 let n
= escape(&src
, &mut buf
);
336 assert_eq
!(&buf
[0..6], src
);
338 let src
= [0, 1, FEND
, 3, 4, 5];
339 let n
= escape(&src
, &mut buf
);
341 assert_eq
!(&buf
[0..7], &[0, 1, FESC
, TFEND
, 3, 4, 5]);
343 let src
= [0, 1, 2, 3, 4, FESC
];
344 let n
= escape(&src
, &mut buf
);
346 assert_eq
!(&buf
[0..7], &[0, 1, 2, 3, 4, FESC
, TFESC
]);
351 let mut buf
= [0u8; 1024];
353 let src
= [0, 1, 2, 3, 4, 5];
354 let n
= unescape(&src
, &mut buf
);
356 assert_eq
!(&buf
[0..6], src
);
358 let src
= [0, 1, TFESC
, 3, TFEND
, 5];
359 let n
= unescape(&src
, &mut buf
);
361 assert_eq
!(&buf
[0..6], src
);
363 let src
= [0, 1, FESC
, TFEND
, 3, 4, 5];
364 let n
= unescape(&src
, &mut buf
);
366 assert_eq
!(&buf
[0..6], &[0, 1, FEND
, 3, 4, 5]);
368 let src
= [0, 1, 2, 3, 4, FESC
, TFESC
];
369 let n
= unescape(&src
, &mut buf
);
371 assert_eq
!(&buf
[0..6], &[0, 1, 2, 3, 4, FESC
]);
375 fn basic_packet_roundtrip() {
376 let f
= KissFrame
::new_basic_packet(&[0, 1, 2, 3]).unwrap
();
377 assert_eq
!(f
.as_bytes(), &[FEND
, 0, 0, 1, 2, 3, FEND
]);
378 let mut buf
= [0u8; 1024];
379 let n
= f
.decode_payload(&mut buf
).unwrap
();
380 assert_eq
!(&buf
[..n
], &[0, 1, 2, 3]);