dot15d4_frame/ie/
headers.rs

1//! IEEE 802.15.4 Header Information Element reader and writers.
2
3use crate::time::Duration;
4use crate::{Error, Result};
5use dot15d4_macros::frame;
6
7/// A reader/writer for the IEEE 802.15.4 Header Information Elements
8#[derive(Debug, Eq, PartialEq, Clone, Copy)]
9pub struct HeaderInformationElement<T: AsRef<[u8]>> {
10    data: T,
11}
12
13impl<T: AsRef<[u8]>> HeaderInformationElement<T> {
14    /// Create a new [`HeaderInformationElement`] reader/writer from a given
15    /// buffer.
16    ///
17    /// # Errors
18    ///
19    /// Returns an error if the length field is less than 2.
20    pub fn new(data: T) -> Result<Self> {
21        let ie = Self::new_unchecked(data);
22
23        if !ie.check_len() {
24            return Err(Error);
25        }
26
27        Ok(ie)
28    }
29
30    /// Returns `false` if the buffer is too short to contain the Header
31    /// Information Element.
32    fn check_len(&self) -> bool {
33        self.data.as_ref().len() >= 2
34    }
35
36    /// Create a new [`HeaderInformationElement`] reader/writer from a given
37    /// buffer without length checking.
38    pub fn new_unchecked(data: T) -> Self {
39        Self { data }
40    }
41
42    /// Returns `true` when the length field is 0.
43    #[must_use]
44    pub fn is_empty(&self) -> bool {
45        self.len() == 0
46    }
47
48    /// Return the length field value.
49    pub fn len(&self) -> usize {
50        let b = &self.data.as_ref()[0..2];
51        u16::from_le_bytes([b[0], b[1]]) as usize & 0b1111_1110
52    }
53
54    /// Return the [`HeaderElementId`].
55    pub fn element_id(&self) -> HeaderElementId {
56        let b = &self.data.as_ref()[0..2];
57        let id = (u16::from_le_bytes([b[0], b[1]]) >> 7) & 0b1111_1111;
58        HeaderElementId::from(id as u8)
59    }
60
61    /// Return the content of this Header Information Element.
62    pub fn content(&self) -> &[u8] {
63        &self.data.as_ref()[2..][..self.len()]
64    }
65}
66
67impl<T: AsRef<[u8]> + AsMut<[u8]>> HeaderInformationElement<T> {
68    /// Clear the content of this Header Information Element.
69    pub fn clear(&mut self) {
70        self.data.as_mut().fill(0);
71    }
72
73    /// Set the length field.
74    pub fn set_length(&mut self, len: u16) {
75        const MASK: u16 = 0b1111_1110;
76
77        let b = &mut self.data.as_mut()[0..2];
78        let value = u16::from_le_bytes([b[0], b[1]]) & !MASK;
79        let value = value | (len & MASK);
80        b[0..2].copy_from_slice(&value.to_le_bytes());
81    }
82
83    /// Set the element ID field.
84    pub fn set_element_id(&mut self, id: HeaderElementId) {
85        const SHIFT: u16 = 7;
86        const MASK: u16 = 0b0111_1111_1000_0000;
87
88        let b = &mut self.data.as_mut()[0..2];
89        let value = u16::from_le_bytes([b[0], b[1]]) & !MASK;
90        let value = value | (((id as u16) << SHIFT) & MASK);
91        b[0..2].copy_from_slice(&value.to_le_bytes());
92    }
93
94    /// Return the content of this Header Information Element.
95    pub fn content_mut(&mut self) -> &mut [u8] {
96        &mut self.data.as_mut()[2..]
97    }
98}
99
100impl<T: AsRef<[u8]>> core::fmt::Display for HeaderInformationElement<T> {
101    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
102        let id = self.element_id();
103        match id {
104            HeaderElementId::HeaderTermination1 | HeaderElementId::HeaderTermination2 => {
105                write!(f, "{:?}", id)
106            }
107            HeaderElementId::SimplifiedSuperframeSpecification => {
108                write!(
109                    f,
110                    "{} {:?}",
111                    id,
112                    SimplifiedSuperframeSpecification::new(self.content())
113                )
114            }
115            HeaderElementId::TimeCorrection => {
116                let Ok(tc) = TimeCorrection::new(self.content()) else {
117                    return write!(f, "{:?}({:0x?})", id, self.content());
118                };
119                write!(f, "{} {}", id, tc)
120            }
121            id => write!(f, "{:?}({:0x?})", id, self.content()),
122        }
123    }
124}
125
126/// Header Information Element ID.
127#[derive(Debug, Eq, PartialEq, Clone, Copy)]
128pub enum HeaderElementId {
129    /// Vendor specific header.
130    VendorSpecificHeader = 0x00,
131    /// Csl header.
132    Csl = 0x1a,
133    /// Rit header.
134    Rit = 0x1b,
135    /// Dsme Pan Descriptor header.
136    DsmePanDescriptor = 0x1c,
137    /// Rendezvous Time header.
138    RendezvousTime = 0x1d,
139    /// Time Correction header.
140    TimeCorrection = 0x1e,
141    /// Extended Dsme Pan Descriptor header.
142    ExtendedDsmePanDescriptor = 0x21,
143    /// Fragment Sequence Context Description header.
144    FragmentSequenceContextDescription = 0x22,
145    /// Simplified Superframe Specification header.
146    SimplifiedSuperframeSpecification = 0x23,
147    /// Simplified Gts Specification header.
148    SimplifiedGtsSpecification = 0x24,
149    /// Lecim Capabilities header.
150    LecimCapabilities = 0x25,
151    /// Trle Descriptor header.
152    TrleDescriptor = 0x26,
153    /// Rcc Capabilities header.
154    RccCapabilities = 0x27,
155    /// Rccn Descriptor header.
156    RccnDescriptor = 0x28,
157    /// Global Time header.
158    GlobalTime = 0x29,
159    /// Da header.
160    Da = 0x2b,
161    /// Header Termination 1.
162    HeaderTermination1 = 0x7e,
163    /// Header Termination 2.
164    HeaderTermination2 = 0x7f,
165    /// Unkown header.
166    Unkown,
167}
168
169impl From<u8> for HeaderElementId {
170    fn from(value: u8) -> Self {
171        match value {
172            0x00 => Self::VendorSpecificHeader,
173            0x1a => Self::Csl,
174            0x1b => Self::Rit,
175            0x1c => Self::DsmePanDescriptor,
176            0x1d => Self::RendezvousTime,
177            0x1e => Self::TimeCorrection,
178            0x21 => Self::ExtendedDsmePanDescriptor,
179            0x22 => Self::FragmentSequenceContextDescription,
180            0x23 => Self::SimplifiedSuperframeSpecification,
181            0x24 => Self::SimplifiedGtsSpecification,
182            0x25 => Self::LecimCapabilities,
183            0x26 => Self::TrleDescriptor,
184            0x27 => Self::RccCapabilities,
185            0x28 => Self::RccnDescriptor,
186            0x29 => Self::GlobalTime,
187            0x2b => Self::Da,
188            0x7e => Self::HeaderTermination1,
189            0x7f => Self::HeaderTermination2,
190            _ => Self::Unkown,
191        }
192    }
193}
194
195impl core::fmt::Display for HeaderElementId {
196    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
197        match self {
198            Self::TimeCorrection => write!(f, "Time Correction"),
199            _ => write!(f, "{:?}", self),
200        }
201    }
202}
203
204/// An [`Iterator`] over [`HeaderInformationElement`].
205#[derive(Debug)]
206pub struct HeaderInformationElementsIterator<'f> {
207    pub(crate) data: &'f [u8],
208    pub(crate) offset: usize,
209    pub(crate) terminated: bool,
210}
211
212impl HeaderInformationElementsIterator<'_> {
213    /// Returns the offset of the next Header Information Element.
214    pub fn offset(&self) -> usize {
215        self.offset
216    }
217}
218
219impl<'f> Iterator for HeaderInformationElementsIterator<'f> {
220    type Item = HeaderInformationElement<&'f [u8]>;
221
222    fn next(&mut self) -> Option<Self::Item> {
223        if self.terminated {
224            None
225        } else {
226            let ie = HeaderInformationElement::new(&self.data[self.offset..]).ok()?;
227
228            self.terminated = matches!(
229                ie.element_id(),
230                HeaderElementId::HeaderTermination1 | HeaderElementId::HeaderTermination2
231            );
232
233            self.offset += ie.len() + 2;
234
235            if self.offset >= self.data.len() {
236                self.terminated = true;
237            }
238
239            Some(ie)
240        }
241    }
242}
243
244/// Vendor Specific Header Information Element.
245#[frame]
246#[derive(Debug)]
247pub struct VendorSpecific {
248    #[bytes(3)]
249    /// Returns the vendor OUI field.
250    vendor_oui: u32,
251
252    #[bytes(0)]
253    /// Returns the vendor specific payload.
254    vendor_specific_payload: &[u8],
255}
256
257/// CSL Header Information Element.
258#[frame]
259#[derive(Debug)]
260pub struct Csl {
261    /// Return the CSL phase field value.
262    csl_phase: u16,
263    /// Return the CSL period field value.
264    csl_period: u16,
265    #[condition(self.buffer.as_ref().len() > 4)]
266    /// Return the rendezvous time field value.
267    rendezvous_time: u16,
268}
269
270/// RIT Header Information Element.
271#[frame]
272#[derive(Debug)]
273pub struct Rit {
274    /// Return the time to first listen field value.
275    time_to_first_listen: u8,
276    /// Return the number of repeat listen field value.
277    number_of_repeat_listen: u8,
278    /// Return the repeat listen interval field value.
279    repeat_listen_interval: u16,
280}
281
282/// DSME Superframe Specification Header Information Element.
283#[frame]
284pub struct DsmeSuperframeSpecification {
285    #[bits(4)]
286    /// Return the multi superframe order field value.
287    multi_superframe_order: u8,
288    #[bits(1)]
289    /// Return the channel diversity mode field value.
290    channel_diversity_mode: bool,
291    #[bits(1)]
292    _reserved: bool,
293    #[bits(1)]
294    /// Return the cap reduction field value.
295    cap_reduction: bool,
296    #[bits(1)]
297    /// Return the deferred beacon field value.
298    deferred_beacon: bool,
299}
300
301/// Time Synchronization Specification Header Information Element.
302#[frame]
303pub struct TimeSynchronizationSpecification {
304    #[bytes(8)]
305    // TODO: use a Duration type
306    /// Return the beacon timestamp field value.
307    beacon_timestamp: &[u8],
308    /// Return the beacon offset timestamp field value.
309    beacon_offset_timestamp: u16,
310}
311
312/// Channel Hopping Specification Header Information Element.
313#[frame]
314pub struct ChannelHoppingSpecification {
315    /// Return the hopping sequence ID field value.
316    hopping_sequence_id: u8,
317    /// Return the PAN coordinator BSN field value.
318    pan_coordinator_bsn: u8,
319    /// Return the channel offset field value.
320    channel_offset: u16,
321    /// Return the channel offset bitmap length field value.
322    channel_offset_bitmap_length: u8,
323    #[bytes(0)]
324    /// Return the channel offset bitmap field value.
325    channel_offset_bitmap: &[u8],
326}
327
328/// Renzdevous Time Header Information Element.
329#[frame]
330pub struct RendezvousTime {
331    /// Return the rendezvous time field value.
332    rendezvous_time: u16,
333    /// Return the wake-up interval field value.
334    wake_up_interval: u16,
335}
336
337/// A reader/writer for the IEEE 802.15.4 Time Correction Header Information
338/// Element.
339pub struct TimeCorrection<T: AsRef<[u8]>> {
340    buffer: T,
341}
342
343impl<T: AsRef<[u8]>> TimeCorrection<T> {
344    /// Create a new [`TimeCorrection`] reader/writer from a given buffer.
345    ///
346    /// # Errors
347    ///
348    /// Returns an error if the buffer is too short.
349    pub fn new(buffer: T) -> Result<Self> {
350        let ie = Self::new_unchecked(buffer);
351
352        if !ie.check_len() {
353            return Err(Error);
354        }
355
356        Ok(ie)
357    }
358
359    /// Returns `false` if the buffer is too short to contain the Time
360    /// Correction field.
361    fn check_len(&self) -> bool {
362        self.buffer.as_ref().len() >= 2
363    }
364
365    /// Create a new [`TimeCorrection`] reader/writer from a given buffer
366    /// without length checking.
367    pub fn new_unchecked(buffer: T) -> Self {
368        Self { buffer }
369    }
370
371    #[allow(clippy::len_without_is_empty)]
372    /// Returns the length of the Time Correction field.
373    pub const fn len(&self) -> usize {
374        2
375    }
376
377    /// Return the time correction value in us.
378    pub fn time_correction(&self) -> Duration {
379        let b = &self.buffer.as_ref()[0..2];
380        let time = ((u16::from_le_bytes([b[0], b[1]]) & 0x0fff) << 4) as i16;
381        Duration::from_us((time >> 4) as i64)
382    }
383
384    /// Returns `true` when the frame is not acknowledged.
385    pub fn nack(&self) -> bool {
386        let b = &self.buffer.as_ref()[0..2];
387        i16::from_le_bytes([b[0], b[1]]) & (0x8000u16 as i16) != 0
388    }
389}
390
391impl<T: AsRef<[u8]> + AsMut<[u8]>> TimeCorrection<T> {
392    /// Set the time correction value.
393    pub fn set_time_correction(&mut self, time_correction: Duration) {
394        let time = (((time_correction.as_us() as i16) << 4) >> 4) & 0x0fff;
395        let b = &mut self.buffer.as_mut()[0..2];
396        b[0..2].copy_from_slice(&time.to_le_bytes());
397    }
398
399    /// Set the NACK field.
400    pub fn set_nack(&mut self, nack: bool) {
401        let b = &mut self.buffer.as_mut()[0..2];
402        let value = i16::from_le_bytes([b[0], b[1]]);
403        if nack {
404            b[0..2].copy_from_slice(&((value | (0x8000_u16 as i16)) as u16).to_le_bytes());
405        } else {
406            b[0..2].copy_from_slice(&((value & 0x7fff) as u16).to_le_bytes());
407        }
408    }
409}
410
411impl<T: AsRef<[u8]>> core::fmt::Display for TimeCorrection<T> {
412    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
413        write!(
414            f,
415            "{}, nack: {}",
416            self.time_correction(),
417            self.nack() as usize
418        )
419    }
420}
421
422#[frame]
423#[derive(Debug)]
424/// A reader/writer for the IEEE 802.15.4 Simplified Superframe Specification
425/// Header Information Element.
426pub struct SimplifiedSuperframeSpecification {
427    /// Returns the timestamp field value.
428    timestamp: u16,
429    #[bytes(2)]
430    /// Returns the superframe specification field value.
431    superframe_specification: SuperframeSpecification,
432    #[bytes(2)]
433    /// Returns the CFP specification field value.
434    cfp_specification: CfpSpecification,
435}
436
437#[frame]
438#[derive(Debug)]
439/// A reader/writer for the IEEE 802.15.4 Superframe Specification Header
440/// Information Element.
441pub struct SuperframeSpecification {
442    /// Return the beacon order field value.
443    #[bits(4)]
444    #[into(BeaconOrder)]
445    beacon_order: u8,
446    /// Return the superframe order field value.
447    #[bits(4)]
448    #[into(SuperframeOrder)]
449    superframe_order: u8,
450    #[bits(4)]
451    /// Return the final cap slot field value.
452    final_cap_slot: u8,
453    #[bits(1)]
454    /// Return the battery life extension field value.
455    battery_life_extension: bool,
456    #[bits(1)]
457    _reserved: bool,
458    #[bits(1)]
459    /// Return the PAN coordinator field value.
460    pan_coordinator: bool,
461    #[bits(1)]
462    /// Return the association permit field value.
463    association_permit: bool,
464}
465
466#[derive(Debug, Eq, PartialEq, Clone, Copy)]
467#[repr(u8)]
468/// Indicates the frequency at which the beacon is transmitted.
469pub enum BeaconOrder {
470    /// The beacon is transmitted at an interval:
471    /// `base_super_frame_duration * 2^{beacon_order}`.
472    Order(u8),
473    /// The beacon is transmitted on demand.
474    OnDemand,
475}
476
477impl From<u8> for BeaconOrder {
478    fn from(value: u8) -> Self {
479        match value {
480            value @ 0..=14 => Self::Order(value),
481            _ => Self::OnDemand,
482        }
483    }
484}
485impl From<BeaconOrder> for u8 {
486    fn from(value: BeaconOrder) -> Self {
487        match value {
488            BeaconOrder::Order(value) => value,
489            BeaconOrder::OnDemand => 15,
490        }
491    }
492}
493
494#[derive(Debug, Eq, PartialEq, Clone, Copy)]
495#[repr(u8)]
496///  The lenght of the active portion of the superframe.
497pub enum SuperframeOrder {
498    /// The superframe duration is calculated with:
499    /// `base_super_frame_duration * 2^{superframe_order}`
500    Order(u8),
501    /// The superframe is inactive after the the beacon.
502    Inactive,
503}
504
505impl From<u8> for SuperframeOrder {
506    fn from(value: u8) -> Self {
507        match value {
508            value @ 0..=14 => Self::Order(value),
509            _ => Self::Inactive,
510        }
511    }
512}
513impl From<SuperframeOrder> for u8 {
514    fn from(value: SuperframeOrder) -> Self {
515        match value {
516            SuperframeOrder::Order(value) => value,
517            SuperframeOrder::Inactive => 15,
518        }
519    }
520}
521
522#[frame]
523#[derive(Debug)]
524/// A reader/writer for the IEEE 802.15.4 CFP Specification Header Information
525/// Element.
526pub struct CfpSpecification {
527    #[bits(3)]
528    /// Return the GTS field value.
529    gts_count: u8,
530    #[bits(5)]
531    /// Return the first CFP slot field value.
532    first_cfp_slot: u8,
533    #[bits(4)]
534    /// Return the last CFP slot field value.
535    last_cfp_slot: u8,
536    #[bits(1)]
537    /// Return the CFP field value.
538    gts_permit: bool,
539}
540
541#[frame]
542#[derive(Debug)]
543/// Guaranteed Time Slot specification.
544pub struct GtsSpecification {
545    #[bits(3)]
546    /// GTS descriptor count.
547    descriptor_count: u8,
548    #[bits(4)]
549    _reserved: u8,
550    /// GTS is permitted.
551    #[bits(1)]
552    gts_permit: bool,
553}
554
555/// Guaranteed Timeslot Descriptor
556#[frame(no_constructor)]
557pub struct GtsSlot {
558    /// Short address of the intended device.
559    #[bytes(2)]
560    #[into(crate::Address)]
561    short_address: &[u8],
562    /// Superframe slot at which the GTS is to begin.
563    #[bits(4)]
564    starting_slot: u8,
565    /// Number of contiguous superframe slots over which the GTS is active.
566    #[bits(4)]
567    length: u8,
568
569    /// The GTS slot direction.
570    #[field]
571    direction: GtsDirection,
572}
573
574impl<T: AsRef<[u8]>> GtsSlot<T> {
575    /// Create a new [`#name`] reader/writer from a given buffer.
576    pub fn new(buffer: T, direction: GtsDirection) -> Result<Self> {
577        let s = Self::new_unchecked(buffer, direction);
578
579        if !s.check_len() {
580            return Err(Error);
581        }
582
583        Ok(s)
584    }
585
586    /// Returns `false` if the buffer is too short to contain this structure.
587    fn check_len(&self) -> bool {
588        self.buffer.as_ref().len() >= Self::size()
589    }
590
591    /// Create a new [`#name`] reader/writer from a given buffer without length
592    /// checking.
593    pub fn new_unchecked(buffer: T, direction: GtsDirection) -> Self {
594        Self { buffer, direction }
595    }
596}
597
598impl<T: AsRef<[u8]>> GtsSpecification<T> {
599    /// Return a [`GtsSlotIterator`].
600    pub fn slots(&self) -> GtsSlotIterator {
601        if self.descriptor_count() == 0 {
602            GtsSlotIterator {
603                data: &[],
604                count: 0,
605                terminated: true,
606            }
607        } else {
608            GtsSlotIterator {
609                data: &self.buffer.as_ref()[1..]
610                    [..1 + self.descriptor_count() as usize * GtsSlot::<T>::size()],
611                count: 0,
612                terminated: false,
613            }
614        }
615    }
616}
617
618/// An [`Iterator`] over GTS slots.
619pub struct GtsSlotIterator<'f> {
620    data: &'f [u8],
621    count: usize,
622    terminated: bool,
623}
624
625impl<'f> Iterator for GtsSlotIterator<'f> {
626    type Item = GtsSlot<&'f [u8]>;
627
628    fn next(&mut self) -> Option<Self::Item> {
629        if self.terminated {
630            None
631        } else {
632            const L: usize = GtsSlot::<&[u8]>::size();
633            if 1 + self.count * L >= self.data.len() {
634                return None;
635            }
636
637            let direction = GtsDirection::from((self.data[0] >> self.count) & 0b1);
638            let descriptor = GtsSlot::new(&self.data[1 + self.count * L..], direction).ok()?;
639
640            self.count += 1;
641            if 1 + self.count * L >= self.data.len() {
642                self.terminated = true;
643            }
644
645            Some(descriptor)
646        }
647    }
648}
649
650/// GTS direciton.
651#[derive(Debug, Eq, PartialEq, Clone, Copy)]
652#[repr(u8)]
653pub enum GtsDirection {
654    /// GTS Receive direction.
655    Receive,
656    /// GTS Transmit direction.
657    Transmit,
658}
659
660impl From<u8> for GtsDirection {
661    fn from(value: u8) -> Self {
662        match value {
663            0b0 => Self::Receive,
664            _ => Self::Transmit,
665        }
666    }
667}
668
669impl From<GtsDirection> for u8 {
670    fn from(value: GtsDirection) -> Self {
671        match value {
672            GtsDirection::Receive => 0b0,
673            GtsDirection::Transmit => 0b1,
674        }
675    }
676}
677
678bitflags::bitflags! {
679    /// Supported Frequency Bands values.
680    pub struct SupportedFrequencyBands: u16 {
681        /// 169 MHz band.
682        const BAND_161_MHZ = 0b0000_0000_0000_0001;
683        /// 216 MHz band.
684        const BAND_216_MHZ = 0b0000_0000_0000_0010;
685        /// 217 MHz band.
686        const BAND_217_MHZ = 0b0000_0000_0000_0100;
687        /// 220 MHz band.
688        const BAND_220_MHZ = 0b0000_0000_0000_1000;
689        /// 450 MHz band.
690        const BAND_450_MHZ = 0b0000_0000_0001_0000;
691        /// 779 MHz band.
692        const BAND_779_MHZ = 0b0000_0000_0010_0000;
693        /// 800 MHz band.
694        const BAND_800_MHZ = 0b0000_0000_0100_0000;
695        /// 806 MHz band.
696        const BAND_806_MHZ = 0b0000_0000_1000_0000;
697        /// 896 MHz band.
698        const BAND_896_MHZ = 0b0000_0001_0000_0000;
699        /// 915 MHz band.
700        const BAND_915_MHZ = 0b0000_0010_0000_0000;
701        /// 928 MHz band.
702        const BAND_928_MHZ = 0b0000_0100_0000_0000;
703        /// 2450 MHz band.
704        const BAND_2450_MHZ = 0b0000_1000_0000_0000;
705        /// 4965 MHz band.
706        const BAND_4965_MHZ = 0b0001_0000_0000_0000;
707        /// 5800 MHz band.
708        const BAND_5800_MHZ = 0b0010_0000_0000_0000;
709        /// Reserved.
710        const BAND_RESERVED = 0b1100_0000_0000_0000;
711    }
712}
713
714bitflags::bitflags! {
715    /// Supported Modulation values.
716    pub struct SupportedRccPhyAndModulation: u16 {
717        /// GMSK 9.6 kbps.
718        const GMSK_9_6_KBPS = 0b0000_0000_0000_0001;
719        /// GMSK 19.2 kbps.
720        const GMSK_19_2_KBPS = 0b0000_0000_0000_0010;
721        /// 4 FSK 9.6 kbps.
722        const FOUR_FSK_9_6_KBPS = 0b0000_0000_0000_0100;
723        /// 4 FSK 19.2 kbps.
724        const FOUR_FSK_19_2_KBPS = 0b0000_0000_0000_1000;
725        /// 4 FSK 38.4 kbps.
726        const FOUR_FSK_38_4_KBPS = 0b0000_0000_0001_0000;
727        /// QPSK 16 kbps.
728        const QPSK_16_KBPS = 0b0000_0000_0010_0000;
729        /// QPSK 32 kbps.
730        const QPSK_32_KBPS = 0b0000_0000_0100_0000;
731        /// PI/4 DQPSK 16 kbps.
732        const PI_4_DQPSK_16_KBPS = 0b0000_0000_1000_0000;
733        /// PI/4 DQPSK 32 kbps.
734        const PI_4_DQPSK_32_KBPS = 0b0000_0001_0000_0000;
735        /// PI/4 DQPSK 64 kbps.
736        const PI_4_DQPSK_64_KBPS = 0b0000_0010_0000_0000;
737        /// DSSS DPSK.
738        const DSSS_DPSK = 0b0000_0100_0000_0000;
739        /// DSSS BPSK.
740        const DSSS_BPSK = 0b0000_1000_0000_0000;
741        /// Reserved.
742        const RESERVED = 0b1111_0000_0000_0000;
743    }
744}
745
746bitflags::bitflags! {
747    /// Supported DSSS DPSK Modulation values.
748    pub struct SupportedDsssDpskModulation: u16 {
749        /// 100 Kcps.
750        const RATE_300_KCPS = 0b0000_0000_0000_0001;
751        /// 600 Kcps.
752        const RATE_600_KCPS = 0b0000_0000_0000_0010;
753        /// 800 Kcps.
754        const RATE_800_KCPS = 0b0000_0000_0000_0100;
755        /// 1 Mcps.
756        const RATE_1_MCPS = 0b0000_0000_0000_1000;
757        /// 1.6 Mcps.
758        const RATE_1_6_MCPS = 0b0000_0000_0001_0000;
759        /// 2 Mcps.
760        const RATE_2_MCPS = 0b0000_0000_0010_0000;
761        /// 3 Mcps.
762        const RATE_3_MCPS = 0b0000_0000_0100_0000;
763        /// 4 Mcps.
764        const RATE_4_MCPS = 0b0000_0000_1000_0000;
765        /// 11 chip spreading.
766        const SPREADING_11_CHIP = 0b0000_0001_0000_0000;
767        /// 15 chip spreading.
768        const SPREADING_15_CHIP = 0b0000_0010_0000_0000;
769        /// 20 chip spreading.
770        const SPREADING_20_CHIP = 0b0000_0100_0000_0000;
771        /// 40 chip spreading.
772        const SPREADING_40_CHIP = 0b0000_1000_0000_0000;
773        /// DSSS DBPSK.
774        const DSSS_DBPSK = 0b0001_0000_0000_0000;
775        /// DSSS DQPSK.
776        const DSSS_DQPSK = 0b0010_0000_0000_0000;
777        /// Reserved.
778        const RESERVED = 0b1100_0000_0000_0000;
779    }
780}
781
782#[cfg(test)]
783mod tests {
784    use super::*;
785
786    #[test]
787    fn superframe_specification() {
788        let data = [0xff, 0x0f];
789        let ie = SuperframeSpecification::new(&data).unwrap();
790        assert_eq!(ie.beacon_order(), BeaconOrder::OnDemand);
791        assert_eq!(ie.superframe_order(), SuperframeOrder::Inactive);
792        assert_eq!(ie.final_cap_slot(), 0x0f);
793        assert!(!ie.battery_life_extension());
794        assert!(!ie.pan_coordinator());
795        assert!(!ie.association_permit());
796    }
797
798    #[test]
799    fn gts_specification() {
800        use crate::Address;
801
802        let data = [0b0000_0000];
803        let gts = GtsSpecification::new(&data).unwrap();
804        assert_eq!(gts.descriptor_count(), 0);
805        assert!(!gts.gts_permit());
806
807        let data = [0b1000_0000];
808        let gts = GtsSpecification::new(&data).unwrap();
809        assert_eq!(gts.descriptor_count(), 0);
810        assert!(gts.gts_permit());
811
812        assert!(gts.slots().next().is_none());
813
814        let data = [0x82, 0x01, 0x34, 0x12, 0x11, 0x78, 0x56, 0x14];
815        let gts = GtsSpecification::new(&data).unwrap();
816
817        assert!(gts.gts_permit());
818        assert_eq!(gts.descriptor_count(), 2);
819
820        let mut slots = gts.slots();
821        let s0 = slots.next().unwrap();
822        assert_eq!(s0.short_address(), Address::Short([0x34, 0x12]));
823        assert_eq!(s0.starting_slot(), 1);
824        assert_eq!(s0.length(), 1);
825        assert_eq!(s0.direction(), GtsDirection::Transmit);
826
827        let s1 = slots.next().unwrap();
828        assert_eq!(s1.short_address(), Address::Short([0x78, 0x56]));
829        assert_eq!(s1.starting_slot(), 4);
830        assert_eq!(s1.length(), 1);
831        assert_eq!(s1.direction(), GtsDirection::Receive);
832
833        assert!(slots.next().is_none());
834    }
835
836    #[test]
837    fn gts_slot() {
838        use crate::Address;
839        let data = [0xab, 0xcd, 0b0101_1010];
840        let slot = GtsSlot::new(&data[..], GtsDirection::Transmit).unwrap();
841        assert_eq!(slot.short_address(), Address::Short([0xab, 0xcd]));
842        assert_eq!(slot.starting_slot(), 0b1010);
843        assert_eq!(slot.length(), 0b0101);
844        assert_eq!(slot.direction(), GtsDirection::Transmit);
845    }
846
847    #[test]
848    fn header_iformation_element_id() {
849        assert_eq!(
850            HeaderElementId::from(0x00),
851            HeaderElementId::VendorSpecificHeader
852        );
853        assert_eq!(HeaderElementId::from(0x1a), HeaderElementId::Csl);
854        assert_eq!(HeaderElementId::from(0x1b), HeaderElementId::Rit);
855        assert_eq!(
856            HeaderElementId::from(0x1c),
857            HeaderElementId::DsmePanDescriptor
858        );
859        assert_eq!(HeaderElementId::from(0x1d), HeaderElementId::RendezvousTime);
860        assert_eq!(HeaderElementId::from(0x1e), HeaderElementId::TimeCorrection);
861        assert_eq!(
862            HeaderElementId::from(0x21),
863            HeaderElementId::ExtendedDsmePanDescriptor
864        );
865        assert_eq!(
866            HeaderElementId::from(0x22),
867            HeaderElementId::FragmentSequenceContextDescription
868        );
869        assert_eq!(
870            HeaderElementId::from(0x23),
871            HeaderElementId::SimplifiedSuperframeSpecification
872        );
873        assert_eq!(
874            HeaderElementId::from(0x24),
875            HeaderElementId::SimplifiedGtsSpecification
876        );
877        assert_eq!(
878            HeaderElementId::from(0x25),
879            HeaderElementId::LecimCapabilities
880        );
881        assert_eq!(HeaderElementId::from(0x26), HeaderElementId::TrleDescriptor);
882        assert_eq!(
883            HeaderElementId::from(0x27),
884            HeaderElementId::RccCapabilities
885        );
886        assert_eq!(HeaderElementId::from(0x28), HeaderElementId::RccnDescriptor);
887        assert_eq!(HeaderElementId::from(0x29), HeaderElementId::GlobalTime);
888        assert_eq!(HeaderElementId::from(0x2b), HeaderElementId::Da);
889        assert_eq!(
890            HeaderElementId::from(0x7e),
891            HeaderElementId::HeaderTermination1
892        );
893        assert_eq!(
894            HeaderElementId::from(0x7f),
895            HeaderElementId::HeaderTermination2
896        );
897        assert_eq!(HeaderElementId::from(0x80), HeaderElementId::Unkown);
898    }
899}