dot15d4_frame/
frame_control.rs

1//! IEEE 802.15.4 Frame Control field readers and writers.
2
3use super::AddressingMode;
4use super::{Error, Result};
5
6/// IEEE 802.15.4 frame type.
7#[derive(Debug, Eq, PartialEq, Clone, Copy)]
8#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
9pub enum FrameType {
10    /// Beacon frame.
11    Beacon = 0b000,
12    /// Data frame.
13    Data = 0b001,
14    /// Acknowledgement frame.
15    Ack = 0b010,
16    /// MAC command frame.
17    MacCommand = 0b011,
18    /// Multipurpose frame.
19    Multipurpose = 0b101,
20    /// Fragmentation frame.
21    FragmentOrFrak = 0b110,
22    /// Extended frame.
23    Extended = 0b111,
24    /// Unknown frame type.
25    Unknown,
26}
27
28impl From<u8> for FrameType {
29    fn from(value: u8) -> Self {
30        match value {
31            0b000 => Self::Beacon,
32            0b001 => Self::Data,
33            0b010 => Self::Ack,
34            0b011 => Self::MacCommand,
35            0b101 => Self::Multipurpose,
36            0b110 => Self::FragmentOrFrak,
37            0b111 => Self::Extended,
38            _ => Self::Unknown,
39        }
40    }
41}
42
43/// IEEE 802.15.4 frame version.
44#[derive(Debug, Eq, PartialEq, Clone, Copy)]
45#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
46pub enum FrameVersion {
47    /// IEEE 802.15.4-2003 frame version.
48    Ieee802154_2003 = 0b00,
49    /// IEEE 802.15.4-2006 frame version.
50    Ieee802154_2006 = 0b01,
51    /// IEEE 802.15.4-2020 frame version.
52    Ieee802154_2020 = 0b10,
53    /// Unknown frame version.
54    Unknown,
55}
56
57impl From<u8> for FrameVersion {
58    fn from(value: u8) -> Self {
59        match value {
60            0b00 => Self::Ieee802154_2003,
61            0b01 => Self::Ieee802154_2006,
62            0b10 => Self::Ieee802154_2020,
63            _ => Self::Unknown,
64        }
65    }
66}
67
68/// A reader/writer for the IEEE 802.15.4 Frame Control field.
69pub struct FrameControl<T: AsRef<[u8]>> {
70    buffer: T,
71}
72
73impl<T: AsRef<[u8]>> FrameControl<T> {
74    /// Create a new [`FrameControl`] reader/writer from a given buffer.
75    ///
76    /// # Errors
77    ///
78    /// Returns an error if the buffer is too short.
79    pub fn new(buffer: T) -> Result<Self> {
80        let fc = Self::new_unchecked(buffer);
81
82        if !fc.check_len() {
83            return Err(Error);
84        }
85
86        Ok(fc)
87    }
88
89    /// Returns `false` if the buffer is too short to contain the Frame Control
90    /// field.
91    fn check_len(&self) -> bool {
92        self.buffer.as_ref().len() >= 2
93    }
94
95    /// Create a new [`FrameControl`] reader/writer from a given buffer without
96    /// length checking.
97    pub fn new_unchecked(buffer: T) -> Self {
98        Self { buffer }
99    }
100
101    /// Return the inner buffer.
102    pub fn into_inner(self) -> T {
103        self.buffer
104    }
105
106    /// Return the [`FrameType`] field.
107    pub fn frame_type(&self) -> FrameType {
108        let b = &self.buffer.as_ref()[..2];
109        FrameType::from((u16::from_le_bytes([b[0], b[1]]) & 0b111) as u8)
110    }
111
112    /// Returns `true` when the security enabled field is set.
113    pub fn security_enabled(&self) -> bool {
114        let b = &self.buffer.as_ref()[..2];
115        ((u16::from_le_bytes([b[0], b[1]]) >> 3) & 0b1) == 1
116    }
117
118    /// Returns `true` when the frame pending field is set.
119    pub fn frame_pending(&self) -> bool {
120        let b = &self.buffer.as_ref()[..2];
121        ((u16::from_le_bytes([b[0], b[1]]) >> 4) & 0b1) == 1
122    }
123
124    /// Returns `true` when the acknowledgement request field is set.
125    pub fn ack_request(&self) -> bool {
126        let b = &self.buffer.as_ref()[..2];
127        ((u16::from_le_bytes([b[0], b[1]]) >> 5) & 0b1) == 1
128    }
129
130    /// Returns `true` when the PAN ID compression field is set.
131    pub fn pan_id_compression(&self) -> bool {
132        let b = &self.buffer.as_ref()[..2];
133        ((u16::from_le_bytes([b[0], b[1]]) >> 6) & 0b1) == 1
134    }
135
136    /// Returns `true` when the sequence number suppression field is set.
137    pub fn sequence_number_suppression(&self) -> bool {
138        let b = &self.buffer.as_ref()[..2];
139        ((u16::from_le_bytes([b[0], b[1]]) >> 8) & 0b1) == 1
140    }
141
142    /// Returns `true` when the information element field is set.
143    pub fn information_elements_present(&self) -> bool {
144        let b = &self.buffer.as_ref()[..2];
145        ((u16::from_le_bytes([b[0], b[1]]) >> 9) & 0b1) == 1
146    }
147
148    /// Return the Destination [`AddressingMode`].
149    pub fn dst_addressing_mode(&self) -> AddressingMode {
150        let b = &self.buffer.as_ref()[..2];
151        let raw = (u16::from_le_bytes([b[0], b[1]]) >> 10) & 0b11;
152        AddressingMode::from(raw as u8)
153    }
154
155    /// Return the Source [`AddressingMode`].
156    pub fn src_addressing_mode(&self) -> AddressingMode {
157        let b = &self.buffer.as_ref()[..2];
158        let raw = (u16::from_le_bytes([b[0], b[1]]) >> 14) & 0b11;
159        AddressingMode::from(raw as u8)
160    }
161
162    /// Return the [`FrameVersion`].
163    pub fn frame_version(&self) -> FrameVersion {
164        let b = &self.buffer.as_ref()[..2];
165        let raw = (u16::from_le_bytes([b[0], b[1]]) >> 12) & 0b11;
166        FrameVersion::from(raw as u8)
167    }
168}
169
170impl<T: AsRef<[u8]> + AsMut<[u8]>> FrameControl<T> {
171    /// Set the frame type field.
172    pub fn set_frame_type(&mut self, frame_type: FrameType) {
173        let b = &mut self.buffer.as_mut()[..2];
174        let mut raw = u16::from_le_bytes([b[0], b[1]]);
175        raw = (raw & !0b111) | ((frame_type as u8) as u16 & 0b111);
176        b.copy_from_slice(&raw.to_le_bytes());
177    }
178
179    /// Set the security enabled field.
180    pub fn set_security_enabled(&mut self, security_enabled: bool) {
181        let b = &mut self.buffer.as_mut()[..2];
182        let mut raw = u16::from_le_bytes([b[0], b[1]]);
183        raw |= (security_enabled as u16) << 3;
184        b.copy_from_slice(&raw.to_le_bytes());
185    }
186
187    /// Set the frame pending field.
188    pub fn set_frame_pending(&mut self, frame_pending: bool) {
189        let b = &mut self.buffer.as_mut()[..2];
190        let mut raw = u16::from_le_bytes([b[0], b[1]]);
191        raw |= (frame_pending as u16) << 4;
192        b.copy_from_slice(&raw.to_le_bytes());
193    }
194
195    /// Set the acknowledgement request field.
196    pub fn set_ack_request(&mut self, ack_request: bool) {
197        let b = &mut self.buffer.as_mut()[..2];
198        let mut raw = u16::from_le_bytes([b[0], b[1]]);
199        raw |= (ack_request as u16) << 5;
200        b.copy_from_slice(&raw.to_le_bytes());
201    }
202
203    /// Set the PAN ID compression field.
204    pub fn set_pan_id_compression(&mut self, pan_id_compression: bool) {
205        let b = &mut self.buffer.as_mut()[..2];
206        let mut raw = u16::from_le_bytes([b[0], b[1]]);
207        raw |= (pan_id_compression as u16) << 6;
208        b.copy_from_slice(&raw.to_le_bytes());
209    }
210
211    /// Set the sequence number suppression field.
212    pub fn set_sequence_number_suppression(&mut self, sequence_number_suppression: bool) {
213        let b = &mut self.buffer.as_mut()[..2];
214        let mut raw = u16::from_le_bytes([b[0], b[1]]);
215        raw |= (sequence_number_suppression as u16) << 8;
216        b.copy_from_slice(&raw.to_le_bytes());
217    }
218
219    /// Set the information element present field.
220    pub fn set_information_elements_present(&mut self, information_elements_present: bool) {
221        let b = &mut self.buffer.as_mut()[..2];
222        let mut raw = u16::from_le_bytes([b[0], b[1]]);
223        raw |= (information_elements_present as u16) << 9;
224        b.copy_from_slice(&raw.to_le_bytes());
225    }
226
227    /// Set the destination addressing mode field.
228    pub fn set_dst_addressing_mode(&mut self, addressing_mode: AddressingMode) {
229        let b = &mut self.buffer.as_mut()[..2];
230        let mut raw = u16::from_le_bytes([b[0], b[1]]);
231        raw = (raw & !(0b11 << 10)) | (((addressing_mode as u8) as u16 & 0b11) << 10);
232        b.copy_from_slice(&raw.to_le_bytes());
233    }
234
235    /// Set the source addressing mode field.
236    pub fn set_src_addressing_mode(&mut self, addressing_mode: AddressingMode) {
237        let b = &mut self.buffer.as_mut()[..2];
238        let mut raw = u16::from_le_bytes([b[0], b[1]]);
239        raw = (raw & !(0b11 << 14)) | (((addressing_mode as u8) as u16 & 0b11) << 14);
240        b.copy_from_slice(&raw.to_le_bytes());
241    }
242
243    /// Set the frame version field.
244    pub fn set_frame_version(&mut self, frame_version: FrameVersion) {
245        let b = &mut self.buffer.as_mut()[..2];
246        let mut raw = u16::from_le_bytes([b[0], b[1]]);
247        raw = (raw & !(0b11 << 12)) | (((frame_version as u8) as u16 & 0b11) << 12);
248        b.copy_from_slice(&raw.to_le_bytes());
249    }
250}
251
252impl<T: AsRef<[u8]>> core::fmt::Display for FrameControl<T> {
253    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
254        writeln!(f, "Frame Control")?;
255        writeln!(f, "  type: {:?}", self.frame_type())?;
256        writeln!(
257            f,
258            "  security enabled: {}",
259            self.security_enabled() as usize
260        )?;
261        writeln!(f, "  frame pending: {}", self.frame_pending() as usize)?;
262        writeln!(f, "  ack request: {}", self.ack_request() as usize)?;
263        writeln!(
264            f,
265            "  pan id compression: {}",
266            self.pan_id_compression() as usize
267        )?;
268        writeln!(
269            f,
270            "  sequence number suppression: {}",
271            self.sequence_number_suppression() as usize
272        )?;
273        writeln!(
274            f,
275            "  information elements present: {}",
276            self.information_elements_present() as usize
277        )?;
278        writeln!(f, "  dst addressing mode: {:?}", self.dst_addressing_mode())?;
279        writeln!(f, "  src addressing mode: {:?}", self.src_addressing_mode())?;
280        writeln!(f, "  frame version: {:?}", self.frame_version())?;
281        Ok(())
282    }
283}
284
285#[cfg(test)]
286mod tests {
287    use super::*;
288
289    #[test]
290    fn bad_length() {
291        let fc = [0x0];
292        assert!(FrameControl::new(&fc).is_err());
293    }
294
295    #[test]
296    fn get_fields() {
297        let fc = [0x0, 0x0];
298        let fc = FrameControl::new(&fc).unwrap();
299        assert_eq!(fc.frame_type(), FrameType::Beacon);
300        assert!(!fc.security_enabled());
301        assert!(!fc.frame_pending());
302        assert!(!fc.ack_request());
303        assert!(!fc.pan_id_compression());
304        assert!(!fc.sequence_number_suppression());
305        assert!(!fc.information_elements_present());
306        assert_eq!(fc.dst_addressing_mode(), AddressingMode::Absent);
307        assert_eq!(fc.src_addressing_mode(), AddressingMode::Absent);
308        assert_eq!(fc.frame_version(), FrameVersion::Ieee802154_2003);
309
310        let fc = [0b0010_1001, 0b1010_1010];
311        let fc = FrameControl::new(&fc).unwrap();
312        assert_eq!(fc.frame_type(), FrameType::Data);
313        assert!(fc.security_enabled());
314        assert!(!fc.frame_pending());
315        assert!(fc.ack_request());
316        assert!(!fc.pan_id_compression());
317        assert!(!fc.sequence_number_suppression());
318        assert!(fc.information_elements_present());
319        assert_eq!(fc.dst_addressing_mode(), AddressingMode::Short);
320        assert_eq!(fc.src_addressing_mode(), AddressingMode::Short);
321        assert_eq!(fc.frame_version(), FrameVersion::Ieee802154_2020);
322    }
323
324    #[test]
325    fn set_fields() {
326        let mut fc = [0x0, 0x0];
327        let mut fc = FrameControl::new_unchecked(&mut fc);
328        fc.set_frame_type(FrameType::Beacon);
329        fc.set_security_enabled(false);
330        fc.set_frame_pending(false);
331        fc.set_ack_request(false);
332        fc.set_pan_id_compression(false);
333        fc.set_sequence_number_suppression(false);
334        fc.set_information_elements_present(false);
335        fc.set_dst_addressing_mode(AddressingMode::Absent);
336        fc.set_src_addressing_mode(AddressingMode::Absent);
337        fc.set_frame_version(FrameVersion::Ieee802154_2003);
338        assert_eq!(*fc.into_inner(), [0x0, 0x0]);
339
340        let mut fc = [0x0, 0x0];
341        let mut fc = FrameControl::new_unchecked(&mut fc);
342        fc.set_frame_type(FrameType::Data);
343        fc.set_security_enabled(true);
344        fc.set_frame_pending(false);
345        fc.set_ack_request(true);
346        fc.set_pan_id_compression(false);
347        fc.set_sequence_number_suppression(false);
348        fc.set_information_elements_present(true);
349        fc.set_dst_addressing_mode(AddressingMode::Short);
350        fc.set_src_addressing_mode(AddressingMode::Short);
351        fc.set_frame_version(FrameVersion::Ieee802154_2020);
352        assert_eq!(*fc.into_inner(), [0b0010_1001, 0b1010_1010]);
353    }
354
355    #[test]
356    fn frame_type() {
357        assert_eq!(FrameType::from(0b000), FrameType::Beacon);
358        assert_eq!(FrameType::from(0b001), FrameType::Data);
359        assert_eq!(FrameType::from(0b010), FrameType::Ack);
360        assert_eq!(FrameType::from(0b011), FrameType::MacCommand);
361        assert_eq!(FrameType::from(0b101), FrameType::Multipurpose);
362        assert_eq!(FrameType::from(0b110), FrameType::FragmentOrFrak);
363        assert_eq!(FrameType::from(0b111), FrameType::Extended);
364        assert_eq!(FrameType::from(0b100), FrameType::Unknown);
365    }
366
367    #[test]
368    fn frame_version() {
369        assert_eq!(FrameVersion::from(0b00), FrameVersion::Ieee802154_2003);
370        assert_eq!(FrameVersion::from(0b01), FrameVersion::Ieee802154_2006);
371        assert_eq!(FrameVersion::from(0b10), FrameVersion::Ieee802154_2020);
372        assert_eq!(FrameVersion::from(0b11), FrameVersion::Unknown);
373    }
374
375    #[test]
376    fn formatting() {
377        let fc = [0b0010_1001, 0b1010_1010];
378        let fc = FrameControl::new(&fc).unwrap();
379        assert_eq!(
380            format!("{}", fc),
381            r"Frame Control
382  type: Data
383  security enabled: 1
384  frame pending: 0
385  ack request: 1
386  pan id compression: 0
387  sequence number suppression: 0
388  information elements present: 1
389  dst addressing mode: Short
390  src addressing mode: Short
391  frame version: Ieee802154_2020
392"
393        );
394    }
395}