From b6d782ed788370a34f306f43865a15ab661e6a42 Mon Sep 17 00:00:00 2001 From: Thomas Karpiniec Date: Wed, 15 Jan 2025 22:03:48 +1100 Subject: [PATCH] Start handling KISS frames in SoftTnc --- m17core/src/address.rs | 4 +-- m17core/src/protocol.rs | 10 ++++++++ m17core/src/tnc.rs | 57 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/m17core/src/address.rs b/m17core/src/address.rs index f6ffa92..48745b2 100755 --- a/m17core/src/address.rs +++ b/m17core/src/address.rs @@ -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. -/// -/// If the "std" feature is enabled then callsigns be converted to or created from strings. #[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', diff --git a/m17core/src/protocol.rs b/m17core/src/protocol.rs index abc9e1b..a325152 100755 --- a/m17core/src/protocol.rs +++ b/m17core/src/protocol.rs @@ -93,6 +93,16 @@ impl PacketType { 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) diff --git a/m17core/src/tnc.rs b/m17core/src/tnc.rs index 0d8bf4a..d4e07b4 100644 --- a/m17core/src/tnc.rs +++ b/m17core/src/tnc.rs @@ -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::{ @@ -315,8 +316,55 @@ impl SoftTnc { 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 { + 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 { + // TODO: handle port 2 } } n @@ -404,6 +452,15 @@ struct 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. -- 2.39.5