Skip to content

Commit

Permalink
add: FrameBuilder for acks
Browse files Browse the repository at this point in the history
The frame builder mechanism makes it easy to create frames.
  • Loading branch information
thvdveld committed Feb 27, 2024
1 parent 08cefde commit dea5357
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 43 deletions.
10 changes: 10 additions & 0 deletions dot15d4/src/frame/addressing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,16 @@ impl Address {
}
}

impl From<Address> 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 {
Expand Down
2 changes: 1 addition & 1 deletion dot15d4/src/frame/repr/ie/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<HeaderInformationElementRepr, 16>,
Expand Down
95 changes: 95 additions & 0 deletions dot15d4/src/frame/repr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
55 changes: 13 additions & 42 deletions dot15d4/src/frame/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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[..]));
Expand Down Expand Up @@ -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()];

Expand Down

0 comments on commit dea5357

Please sign in to comment.