aboutsummaryrefslogtreecommitdiffstats
path: root/src/kiss.rs
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2018-08-26 22:03:10 +0200
committerMatthias P. Braendli <matthias.braendli@mpb.li>2018-08-26 22:04:27 +0200
commit37a60e2d14857c582ad5770a936c6a5647ea2b9e (patch)
tree3751ae13d7d8bba88b93fb50c5d8d28fca80f3b9 /src/kiss.rs
downloadraspi-rfm95-kiss-37a60e2d14857c582ad5770a936c6a5647ea2b9e.tar.gz
raspi-rfm95-kiss-37a60e2d14857c582ad5770a936c6a5647ea2b9e.tar.bz2
raspi-rfm95-kiss-37a60e2d14857c582ad5770a936c6a5647ea2b9e.zip
Add initial code
Diffstat (limited to 'src/kiss.rs')
-rw-r--r--src/kiss.rs183
1 files changed, 183 insertions, 0 deletions
diff --git a/src/kiss.rs b/src/kiss.rs
new file mode 100644
index 0000000..397922d
--- /dev/null
+++ b/src/kiss.rs
@@ -0,0 +1,183 @@
+// Taken from ax25-rs, which is
+// SPDX-License-Identifier: Apache-2.0
+use std::io;
+use std::io::prelude::*;
+use std::io::{Read, Write};
+
+const FEND: u8 = 0xC0;
+const FESC: u8 = 0xDB;
+const TFEND: u8 = 0xDC;
+const TFESC: u8 = 0xDD;
+
+pub struct KissDecoder<'a> {
+ stream: &'a Read,
+ buffer: Vec<u8>
+}
+
+impl<'a> KissDecoder<'a> {
+ pub fn new<T>(stream: &T) -> io::Result<KissDecoder>
+ where T: Read
+ {
+ Ok(KissDecoder {
+ stream: stream,
+ buffer: Vec::new()
+ })
+ }
+
+ pub fn receive_frame(&mut self) -> io::Result<Vec<u8>> {
+ loop {
+ if let Some(frame) = make_frame_from_buffer(&mut self.buffer) {
+ return Ok(frame);
+ }
+ let mut buf = vec![0u8; 1024];
+ let n_bytes = self.stream.read(&mut buf)?;
+ self.buffer.extend(buf.iter().take(n_bytes));
+ }
+ }
+}
+
+/*
+pub struct KissEncoder {
+ stream: Write,
+ buffer: Vec<u8>
+}
+
+impl KissEncoder {
+ pub fn new(stream: Write) -> io::Result<KissEncoder> {
+ Ok(KissEncoder {
+ stream: stream,
+ buffer: Vec::new()
+ })
+ }
+
+ pub fn send_frame(&mut self, frame: &[u8]) -> io::Result<()> {
+ // 0x00 is the KISS command byte, which is two nybbles
+ // port = 0
+ // command = 0 (all following bytes are a data frame to transmit)
+ self.stream.write(&[FEND, 0x00])?;
+ self.stream.write(frame)?;
+ self.stream.write(&[FEND])?;
+ self.stream.flush()?;
+ Ok(())
+ }
+}
+
+fn make_frame_from_buffer(buffer: &mut Vec<u8>) -> Option<Vec<u8>> {
+ let mut possible_frame = Vec::new();
+
+ enum Scan {
+ LookingForStartMarker,
+ Data,
+ Escaped
+ }
+ let mut state = Scan::LookingForStartMarker;
+ let mut final_idx = 0;
+
+ // Check for possible frame read-only until we know we have a complete frame
+ // If we take one out, clear out buffer up to the final index
+ for (idx, &c) in buffer.iter().enumerate() {
+ match state {
+ Scan::LookingForStartMarker => {
+ if c == FEND {
+ state = Scan::Data;
+ }
+ },
+ Scan::Data => {
+ if c == FEND {
+ if !possible_frame.is_empty() {
+ // Successfully read a non-zero-length frame
+ final_idx = idx;
+ break;
+ }
+ } else if c == FESC {
+ state = Scan::Escaped;
+ } else {
+ possible_frame.push(c);
+ }
+ },
+ Scan::Escaped => {
+ if c == TFEND {
+ possible_frame.push(FEND);
+ } else if c == TFESC {
+ possible_frame.push(FESC);
+ } else if c == FEND {
+ if !possible_frame.is_empty() {
+ // Successfully read a non-zero-length frame
+ final_idx = idx;
+ break;
+ }
+ }
+ state = Scan::Data;
+ }
+ }
+ }
+
+ match final_idx {
+ 0 => None,
+ n => {
+ // Draining up to "n" will leave the final FEND in place
+ // This way we can use it as the start marker for the next frame
+ buffer.drain(0..n);
+ Some(possible_frame)
+ }
+ }
+}
+
+#[test]
+fn test_normal_frame() {
+ let mut rx = vec![FEND, 0x01, 0x02, FEND];
+ assert_eq!(make_frame_from_buffer(&mut rx), Some(vec![0x01, 0x02]));
+ assert_eq!(rx, vec![FEND]);
+}
+
+#[test]
+fn test_trailing_data() {
+ let mut rx = vec![FEND, 0x01, 0x02, FEND, 0x03, 0x04];
+ assert_eq!(make_frame_from_buffer(&mut rx), Some(vec![0x01, 0x02]));
+ assert_eq!(rx, vec![FEND, 0x03, 0x04]);
+}
+
+#[test]
+fn test_leading_data() {
+ let mut rx = vec![0x03, 0x04, FEND, 0x01, 0x02, FEND];
+ assert_eq!(make_frame_from_buffer(&mut rx), Some(vec![0x01, 0x02]));
+ assert_eq!(rx, vec![FEND]);
+}
+
+#[test]
+fn test_consecutive_marker() {
+ let mut rx = vec![FEND, FEND, FEND, 0x01, 0x02, FEND];
+ assert_eq!(make_frame_from_buffer(&mut rx), Some(vec![0x01, 0x02]));
+ assert_eq!(rx, vec![FEND]);
+}
+
+#[test]
+fn test_escapes() {
+ let mut rx = vec![FEND, 0x01, FESC, TFESC, 0x02, FESC, TFEND, 0x03, FEND];
+ assert_eq!(make_frame_from_buffer(&mut rx), Some(vec![0x01, FESC, 0x02, FEND, 0x03]));
+ assert_eq!(rx, vec![FEND]);
+}
+
+#[test]
+fn test_incorrect_escape_skipped() {
+ let mut rx = vec![FEND, 0x01, FESC, 0x04, TFESC /* passes normally without leading FESC */, 0x02, FEND];
+ assert_eq!(make_frame_from_buffer(&mut rx), Some(vec![0x01, TFESC, 0x02]));
+ assert_eq!(rx, vec![FEND]);
+}
+
+#[test]
+fn test_two_frames_single_fend() {
+ let mut rx = vec![FEND, 0x01, 0x02, FEND, 0x03, 0x04, FEND];
+ assert_eq!(make_frame_from_buffer(&mut rx), Some(vec![0x01, 0x02]));
+ assert_eq!(make_frame_from_buffer(&mut rx), Some(vec![0x03, 0x04]));
+ assert_eq!(rx, vec![FEND]);
+}
+
+#[test]
+fn test_two_frames_double_fend() {
+ let mut rx = vec![FEND, 0x01, 0x02, FEND, FEND, 0x03, 0x04, FEND];
+ assert_eq!(make_frame_from_buffer(&mut rx), Some(vec![0x01, 0x02]));
+ assert_eq!(make_frame_from_buffer(&mut rx), Some(vec![0x03, 0x04]));
+ assert_eq!(rx, vec![FEND]);
+}
+*/