From dea5357fbac6042c77f8f420f5e93d8b0db96cf6 Mon Sep 17 00:00:00 2001 From: Thibaut Vandervelden Date: Tue, 27 Feb 2024 17:19:38 +0100 Subject: [PATCH] add: FrameBuilder for acks The frame builder mechanism makes it easy to create frames. --- dot15d4/src/frame/addressing.rs | 10 ++++ dot15d4/src/frame/repr/ie/mod.rs | 2 +- dot15d4/src/frame/repr/mod.rs | 95 ++++++++++++++++++++++++++++++++ dot15d4/src/frame/tests.rs | 55 +++++------------- 4 files changed, 119 insertions(+), 43 deletions(-) diff --git a/dot15d4/src/frame/addressing.rs b/dot15d4/src/frame/addressing.rs index adbe90f..98d1783 100644 --- a/dot15d4/src/frame/addressing.rs +++ b/dot15d4/src/frame/addressing.rs @@ -73,6 +73,16 @@ impl Address { } } +impl From
for AddressingMode { + fn from(value: Address) -> Self { + match value { + Address::Absent => AddressingMode::Absent, + Address::Short(_) => AddressingMode::Short, + Address::Extended(_) => AddressingMode::Extended, + } + } +} + impl core::fmt::Display for Address { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { diff --git a/dot15d4/src/frame/repr/ie/mod.rs b/dot15d4/src/frame/repr/ie/mod.rs index 96b8138..918c31f 100644 --- a/dot15d4/src/frame/repr/ie/mod.rs +++ b/dot15d4/src/frame/repr/ie/mod.rs @@ -12,7 +12,7 @@ use super::super::InformationElements; use heapless::Vec; /// A high-level representation of Information Elements. -#[derive(Debug)] +#[derive(Debug, Default)] pub struct InformationElementsRepr { /// The header information elements. pub header_information_elements: Vec, diff --git a/dot15d4/src/frame/repr/mod.rs b/dot15d4/src/frame/repr/mod.rs index 9f5ee7a..4a3c476 100644 --- a/dot15d4/src/frame/repr/mod.rs +++ b/dot15d4/src/frame/repr/mod.rs @@ -82,3 +82,98 @@ impl<'f> FrameRepr<'f> { } } } + +pub struct FrameBuilder<'p> { + frame: FrameRepr<'p>, +} + +impl<'p> FrameBuilder<'p> { + pub fn new_ack() -> Self { + Self { + frame: FrameRepr { + frame_control: FrameControlRepr { + frame_type: super::FrameType::Ack, + security_enabled: false, + frame_pending: false, + ack_request: false, + pan_id_compression: false, + sequence_number_suppression: true, + information_elements_present: false, + dst_addressing_mode: super::AddressingMode::Absent, + src_addressing_mode: super::AddressingMode::Absent, + frame_version: super::FrameVersion::Ieee802154_2020, + }, + sequence_number: None, + addressing_fields: AddressingFieldsRepr { + dst_pan_id: None, + src_pan_id: None, + dst_address: None, + src_address: None, + }, + information_elements: None, + payload: None, + }, + } + } + + pub fn set_sequence_number(mut self, sequence_number: u8) -> Self { + self.frame.sequence_number = Some(sequence_number); + self.frame.frame_control.sequence_number_suppression = false; + self + } + + pub fn set_dst_pan_id(mut self, pan_id: u16) -> Self { + self.frame.addressing_fields.dst_pan_id = Some(pan_id); + self + } + + pub fn set_src_pan_id(mut self, pan_id: u16) -> Self { + self.frame.addressing_fields.src_pan_id = Some(pan_id); + self + } + + pub fn set_dst_address(mut self, address: super::Address) -> Self { + self.frame.frame_control.dst_addressing_mode = address.into(); + self.frame.addressing_fields.dst_address = Some(address); + self + } + + pub fn set_src_address(mut self, address: super::Address) -> Self { + self.frame.frame_control.src_addressing_mode = address.into(); + self.frame.addressing_fields.src_address = Some(address); + self + } + + pub fn add_header_information_element(mut self, ie: HeaderInformationElementRepr) -> Self { + self.frame.frame_control.information_elements_present = true; + self.frame + .information_elements + .get_or_insert_with(InformationElementsRepr::default) + .header_information_elements + .push(ie) + .unwrap(); + + self + } + + pub fn add_payload_information_element(mut self, ie: PayloadInformationElementRepr) -> Self { + self.frame.frame_control.information_elements_present = true; + self.frame + .information_elements + .get_or_insert_with(InformationElementsRepr::default) + .payload_information_elements + .push(ie) + .unwrap(); + + self + } + + pub fn set_payload(mut self, payload: &'p [u8]) -> Self { + self.frame.payload = Some(payload); + self + } + + pub fn finalize(self) -> FrameRepr<'p> { + self.frame + } +} diff --git a/dot15d4/src/frame/tests.rs b/dot15d4/src/frame/tests.rs index 5c982f9..7fda8cc 100644 --- a/dot15d4/src/frame/tests.rs +++ b/dot15d4/src/frame/tests.rs @@ -54,39 +54,19 @@ fn parse_ack_frame() { #[test] fn emit_ack_frame() { - let frame = FrameRepr { - frame_control: FrameControlRepr { - frame_type: FrameType::Ack, - security_enabled: false, - frame_pending: false, - ack_request: false, - pan_id_compression: false, - sequence_number_suppression: false, - information_elements_present: true, - dst_addressing_mode: AddressingMode::Extended, - src_addressing_mode: AddressingMode::Absent, - frame_version: FrameVersion::Ieee802154_2020, - }, - sequence_number: Some(55), - addressing_fields: AddressingFieldsRepr { - dst_pan_id: Some(0xabcd), - src_pan_id: None, - dst_address: Some(Address::Extended([ - 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, - ])), - src_address: None, - }, - information_elements: Some(InformationElementsRepr { - header_information_elements: Vec::from_iter([ - HeaderInformationElementRepr::TimeCorrection(TimeCorrectionRepr { - time_correction: crate::time::Duration::from_us(-31), - nack: true, - }), - ]), - payload_information_elements: Vec::new(), - }), - payload: None, - }; + let frame = FrameBuilder::new_ack() + .set_sequence_number(55) + .set_dst_pan_id(0xabcd) + .set_dst_address(Address::Extended([ + 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, + ])) + .add_header_information_element(HeaderInformationElementRepr::TimeCorrection( + TimeCorrectionRepr { + time_correction: Duration::from_us(-31), + nack: true, + }, + )) + .finalize(); let mut buffer = vec![0; frame.buffer_len()]; frame.emit(&mut Frame::new_unchecked(&mut buffer[..])); @@ -165,15 +145,6 @@ fn emit_data_frame() { information_elements: None, payload: Some(&[0x2b, 0x00, 0x00, 0x00]), }; - println!( - "buffer len: {}", - [ - 0x41, 0xd8, 0x01, 0xcd, 0xab, 0xff, 0xff, 0xc7, 0xd9, 0xb5, 0x14, 0x00, 0x4b, 0x12, - 0x00, 0x2b, 0x00, 0x00, 0x00, - ] - .len() - ); - println!("frame buffer len: {}", frame.buffer_len()); let mut buffer = vec![0; frame.buffer_len()];