]> code.octet-stream.net Git - m17rt/commitdiff
Start handling KISS frames in SoftTnc
authorThomas Karpiniec <tom.karpiniec@outlook.com>
Wed, 15 Jan 2025 11:03:48 +0000 (22:03 +1100)
committerThomas Karpiniec <tom.karpiniec@outlook.com>
Wed, 15 Jan 2025 11:03:48 +0000 (22:03 +1100)
m17core/src/address.rs
m17core/src/protocol.rs
m17core/src/tnc.rs

index f6ffa9295601195ae26d7a5e11ecf8939224d8ce..48745b2941e320e307e8a95b4342a13ebe24d1d9 100755 (executable)
@@ -10,10 +10,8 @@ pub enum Address {
 ///
 /// May be up to 9 characters long - if it shorter then remaining space is filled with
 /// space characters.
 ///
 /// May be up to 9 characters long - if it shorter then remaining space is filled with
 /// space characters.
-///
-/// If the "std" feature is enabled then callsigns be converted to or created from strings.
 #[derive(Debug, Clone, PartialEq, Eq)]
 #[derive(Debug, Clone, PartialEq, Eq)]
-pub struct Callsign([u8; 9]);
+pub struct Callsign(pub [u8; 9]);
 
 static ALPHABET: [u8; 40] = [
     b' ', b'A', b'B', b'C', b'D', b'E', b'F', b'G', b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
 
 static ALPHABET: [u8; 40] = [
     b' ', b'A', b'B', b'C', b'D', b'E', b'F', b'G', b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
index abc9e1bacbb69a3077ba183244f2f711406e1641..a325152743fc329bac6500ad27e799538601a029 100755 (executable)
@@ -93,6 +93,16 @@ impl PacketType {
 pub struct LsfFrame(pub [u8; 30]);
 
 impl LsfFrame {
 pub struct LsfFrame(pub [u8; 30]);
 
 impl LsfFrame {
+    pub fn new_packet(source: &Address, destination: &Address) -> Self {
+        let mut out = Self([0u8; 30]);
+        out.set_source(source);
+        out.set_destination(destination);
+        out.set_mode(Mode::Packet);
+        out.set_data_type(DataType::Data);
+        out.set_encryption_type(EncryptionType::None);
+        out
+    }
+
     /// Calculate crc of entire frame. If zero, it is a valid frame.
     pub fn check_crc(&self) -> u16 {
         crate::crc::m17_crc(&self.0)
     /// Calculate crc of entire frame. If zero, it is a valid frame.
     pub fn check_crc(&self) -> u16 {
         crate::crc::m17_crc(&self.0)
index 0d8bf4afa17feba8769426d76de7ef88cb4ee3d4..d4e07b4e8344dd6ad9709b146c9c8592d042f3f9 100644 (file)
@@ -1,3 +1,4 @@
+use crate::address::{Address, Callsign};
 use crate::kiss::{KissBuffer, KissFrame, PORT_PACKET_BASIC, PORT_PACKET_FULL, PORT_STREAM};
 use crate::modem::ModulatorFrame;
 use crate::protocol::{
 use crate::kiss::{KissBuffer, KissFrame, PORT_PACKET_BASIC, PORT_PACKET_FULL, PORT_STREAM};
 use crate::modem::ModulatorFrame;
 use crate::protocol::{
@@ -315,8 +316,55 @@ impl SoftTnc {
                 continue;
             };
             if port == PORT_PACKET_BASIC {
                 continue;
             };
             if port == PORT_PACKET_BASIC {
+                if self.packet_full {
+                    continue;
+                }
+                let mut pending = PendingPacket::new();
+                pending.app_data[0] = 0x00; // RAW
+                let Ok(mut len) = kiss_frame.decode_payload(&mut pending.app_data[1..]) else {
+                    continue;
+                };
+                len += 1; // for RAW prefix
+                let packet_crc = crate::crc::m17_crc(&pending.app_data[0..len]);
+                pending.app_data[len..len + 2].copy_from_slice(&packet_crc.to_be_bytes());
+                pending.app_data_len = len + 2;
+                pending.lsf = Some(LsfFrame::new_packet(
+                    &Address::Callsign(Callsign(b"M17RT-PKT".clone())),
+                    &Address::Broadcast,
+                ));
+                self.packet_queue[self.packet_next] = pending;
+                self.packet_next = (self.packet_next + 1) % 4;
+                if self.packet_next == self.packet_curr {
+                    self.packet_full = true;
+                }
             } else if port == PORT_PACKET_FULL {
             } else if port == PORT_PACKET_FULL {
+                if self.packet_full {
+                    continue;
+                }
+                let mut pending = PendingPacket::new();
+                let mut payload = [0u8; 855];
+                let Ok(len) = kiss_frame.decode_payload(&mut payload) else {
+                    continue;
+                };
+                if len < 33 {
+                    continue;
+                }
+                let mut lsf = LsfFrame([0u8; 30]);
+                lsf.0.copy_from_slice(&payload[0..30]);
+                if lsf.check_crc() != 0 {
+                    continue;
+                }
+                pending.lsf = Some(lsf);
+                let app_data_len = len - 30;
+                pending.app_data[0..app_data_len].copy_from_slice(&payload[30..]);
+                pending.app_data_len = app_data_len;
+                self.packet_queue[self.packet_next] = pending;
+                self.packet_next = (self.packet_next + 1) % 4;
+                if self.packet_next == self.packet_curr {
+                    self.packet_full = true;
+                }
             } else if port == PORT_STREAM {
             } else if port == PORT_STREAM {
+                // TODO: handle port 2
             }
         }
         n
             }
         }
         n
@@ -404,6 +452,15 @@ struct PendingPacket {
 }
 
 impl PendingPacket {
 }
 
 impl PendingPacket {
+    fn new() -> Self {
+        Self {
+            lsf: None,
+            app_data: [0u8; 825],
+            app_data_len: 0,
+            app_data_transmitted: 0,
+        }
+    }
+
     /// Returns next frame, not including preamble or EOT.
     ///
     /// False means all data frames have been sent.
     /// Returns next frame, not including preamble or EOT.
     ///
     /// False means all data frames have been sent.