diff --git a/Cargo.toml b/Cargo.toml index fcd2e92..b06112a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,8 @@ readme = "README.md" categories = ["embedded", "network-programming", "no-std"] keywords = ["WPAN"] +[features] + [badges] travis-ci = { repository = "braun-robotics/ieee802154" } @@ -21,6 +23,7 @@ travis-ci = { repository = "braun-robotics/ieee802154" } hash32 = "0.2.1" hash32-derive = "0.1" byte = "0.2.4" +defmt = { version = ">=0.2.0,<0.4", optional = true } [dependencies.ccm] version = "0.4.0" @@ -30,10 +33,9 @@ default-features = false version = "0.3.0" default-features = false - [dev-dependencies] rand = "0.8.3" [dev-dependencies.aes] version = "0.7.0" -default-features = false +default-features = false \ No newline at end of file diff --git a/src/mac/beacon.rs b/src/mac/beacon.rs index 035f58a..fadf991 100644 --- a/src/mac/beacon.rs +++ b/src/mac/beacon.rs @@ -10,6 +10,7 @@ use crate::mac::{ExtendedAddress, ShortAddress}; /// Beacon order is used to calculate the beacon interval #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum BeaconOrder { /// Used to calculate at which interval beacons are sent /// @@ -41,6 +42,7 @@ impl From for u8 { /// Superframe order, amount of time during wich this superframe is active #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum SuperframeOrder { /// Ammount of time that the superframe is active /// @@ -75,6 +77,7 @@ impl From for u8 { /// The superframe specification describes the organisation of frames in the /// air when using superframes and/or periodical beacons. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SuperframeSpecification { /// Beacon order, 0-15, where 15 is on demand. /// @@ -152,6 +155,7 @@ impl TryWrite for SuperframeSpecification { /// Direction of data #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] enum Direction { /// Receive data Receive, @@ -161,6 +165,7 @@ enum Direction { /// Descriptor of the guaranteed time slots (GTSs) #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GuaranteedTimeSlotDescriptor { /// Device short address used by this slot short_address: ShortAddress, @@ -230,6 +235,7 @@ const PERMIT: u8 = 0b1000_0000; /// Information of the guaranteed time slots (GTSs) #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GuaranteedTimeSlotInformation { /// Permit GTS pub permit: bool, @@ -348,6 +354,7 @@ const EXTENDED_MASK: u8 = 0b0111_0000; /// 0 - 2 3 4 - 6 7 bit /// ``` #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PendingAddress { short_address_count: usize, short_addresses: [ShortAddress; 7], @@ -433,6 +440,7 @@ impl TryWrite for PendingAddress { /// Beacon frame #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Beacon { /// Superframe specification pub superframe_spec: SuperframeSpecification, diff --git a/src/mac/command.rs b/src/mac/command.rs index 06c8fb1..cc1c76c 100644 --- a/src/mac/command.rs +++ b/src/mac/command.rs @@ -42,6 +42,7 @@ const CAP_ALLOCATE_ADDRESS: u8 = 0x80; /// /// Sent with association request to report the capabilities of the device. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct CapabilityInformation { /// Full-function device (FFD) or a reduced-function device (RFD) /// RFD and FFD have different function sets. @@ -125,6 +126,7 @@ extended_enum!( /// /// Changes to the PAN sent by the coordinator. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct CoordinatorRealignmentData { /// PAN id that the coordinator will use pub pan_id: PanId, @@ -185,6 +187,7 @@ const GTSC_ALLOCATION: u8 = 0x20; /// /// GTS configuration requested with the guaranteed time slot request command. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GuaranteedTimeSlotCharacteristics { /// Number of slots requested pub count: u8, @@ -221,6 +224,7 @@ impl From for u8 { /// MAC commands #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Command { /// Association request, request association to a PAN AssociationRequest(CapabilityInformation), diff --git a/src/mac/frame/frame_control.rs b/src/mac/frame/frame_control.rs index b0c8374..fe157dd 100644 --- a/src/mac/frame/frame_control.rs +++ b/src/mac/frame/frame_control.rs @@ -8,6 +8,7 @@ use super::DecodeError; /// /// [`Header`]: super::header::Header #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum FrameType { /// Beacon Beacon = 0b000, @@ -20,6 +21,15 @@ pub enum FrameType { /// MAC command MacCommand = 0b011, + + /// Multipurpose + Multipurpose = 0b101, + + /// Fragment of Fragment Ack + FragOrFragAck = 0b110, + + /// Extended + Extended = 0b111, } impl FrameType { @@ -41,6 +51,9 @@ impl FrameType { 0b001 => Some(FrameType::Data), 0b010 => Some(FrameType::Acknowledgement), 0b011 => Some(FrameType::MacCommand), + 0b101 => Some(FrameType::Multipurpose), + 0b110 => Some(FrameType::FragOrFragAck), + 0b111 => Some(FrameType::Extended), _ => None, } } @@ -48,6 +61,7 @@ impl FrameType { /// Defines version information for a frame #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum FrameVersion { /// A frame conforming to the 802.15.4-2003 standard Ieee802154_2003 = 0b00, @@ -92,6 +106,7 @@ impl FrameVersion { /// assert_eq!(address_mode, AddressMode::Short); /// ``` #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum AddressMode { /// PAN identifier and address field are not present None = 0b00, @@ -150,6 +165,8 @@ pub mod offset { pub const PENDING: u16 = 4; pub const ACK: u16 = 5; pub const PAN_ID_COMPRESS: u16 = 6; + pub const SEQ_NO_SUPPRESS: u16 = 8; + pub const IE_PRESENT: u16 = 9; pub const DEST_ADDR_MODE: u16 = 10; pub const VERSION: u16 = 12; pub const SRC_ADDR_MODE: u16 = 14u16; @@ -161,6 +178,8 @@ pub mod mask { pub const PENDING: u16 = 0x0010; pub const ACK: u16 = 0x0020; pub const PAN_ID_COMPRESS: u16 = 0x0040; + pub const SEQ_NO_SUPPRESS: u16 = 0x0100; + pub const IE_PRESENT: u16 = 0x0200; pub const DEST_ADDR_MODE: u16 = 0x0C00; pub const VERSION: u16 = 0x3000; pub const SRC_ADDR_MODE: u16 = 0xC000; diff --git a/src/mac/frame/header.rs b/src/mac/frame/header.rs index 53afb82..96b6595 100644 --- a/src/mac/frame/header.rs +++ b/src/mac/frame/header.rs @@ -22,6 +22,7 @@ use super::{security::AuxiliarySecurityHeader, EncodeError}; /// /// [MAC frame format start at 5.2]: http://ecee.colorado.edu/~liue/teaching/comm_standards/2015S_zigbee/802.15.4-2011.pdf #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Header { // * Frame Control Field * / /// Frame Type @@ -51,6 +52,12 @@ pub struct Header { /// present. pub pan_id_compress: bool, + /// Suppress sequence number + pub seq_no_suppress: bool, + + /// Information element present + pub ie_present: bool, + /// Frame version pub version: FrameVersion, @@ -122,8 +129,14 @@ impl TryRead<'_> for Header { let pan_id_compress = ((bits & mask::PAN_ID_COMPRESS) >> offset::PAN_ID_COMPRESS) as u8; + let seq_no_suppress = + ((bits & mask::SEQ_NO_SUPPRESS) >> offset::SEQ_NO_SUPPRESS) as u8; + let ie_present = + ((bits & mask::IE_PRESENT) >> offset::IE_PRESENT) as u8; + let dest_addr_mode = ((bits & mask::DEST_ADDR_MODE) >> offset::DEST_ADDR_MODE) as u8; + let version = ((bits & mask::VERSION) >> offset::VERSION) as u8; let src_addr_mode = ((bits & mask::SRC_ADDR_MODE) >> offset::SRC_ADDR_MODE) as u8; @@ -140,6 +153,8 @@ impl TryRead<'_> for Header { let frame_pending = frame_pending > 0; let ack_request = ack_request > 0; let pan_id_compress = pan_id_compress > 0; + let seq_no_suppress = seq_no_suppress > 0; + let ie_present = ie_present > 0; /* Decode header depending on Frame Control Fields */ @@ -202,6 +217,8 @@ impl TryRead<'_> for Header { frame_pending, ack_request, pan_id_compress, + seq_no_suppress, + ie_present, version, seq, destination, @@ -295,6 +312,7 @@ where /// let pan_id = PanId(0x0123); /// ``` #[derive(Clone, Copy, Debug, Eq, Hash, Hash32, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PanId(pub u16); impl PanId { @@ -332,6 +350,7 @@ impl TryRead<'_> for PanId { /// let short_address = ShortAddress(0x0123); /// ``` #[derive(Clone, Copy, Debug, Eq, Hash, Hash32, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct ShortAddress(pub u16); impl ShortAddress { @@ -371,6 +390,7 @@ impl TryRead<'_> for ShortAddress { /// let ext_address = ExtendedAddress(0x0123456789abcdef); /// ``` #[derive(Clone, Copy, Debug, Eq, Hash, Hash32, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct ExtendedAddress(pub u64); impl ExtendedAddress { @@ -400,6 +420,7 @@ impl TryRead<'_> for ExtendedAddress { /// An address that might contain an PAN ID and address #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Address { /// Short (16-bit) address and PAN ID (16-bit) Short(PanId, ShortAddress), @@ -408,6 +429,7 @@ pub enum Address { } #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] enum AddressEncoding { Normal, Compressed, diff --git a/src/mac/frame/mod.rs b/src/mac/frame/mod.rs index 9e7803c..4d12839 100644 --- a/src/mac/frame/mod.rs +++ b/src/mac/frame/mod.rs @@ -114,6 +114,8 @@ use self::security::{ /// /// let frame = Frame { /// header: Header { +/// ie_present: false, +/// seq_no_suppress: false, /// frame_type: FrameType::Data, /// frame_pending: false, /// ack_request: false, @@ -150,6 +152,7 @@ use self::security::{ /// [decode]: #method.try_read /// [encode]: #method.try_write #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Frame<'p> { /// Header pub header: Header, @@ -377,6 +380,7 @@ impl<'a> TryRead<'a, FooterMode> for Frame<'a> { /// /// [`Frame::try_write`](Frame::try_write) #[derive(Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum FooterMode { /// Don't read/write the footer None, @@ -392,6 +396,7 @@ impl Default for FooterMode { /// Content of a frame #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum FrameContent { /// Beacon frame content Beacon(Beacon), @@ -401,6 +406,14 @@ pub enum FrameContent { Acknowledgement, /// MAC command frame Command(Command), + /// Multipurpose frame + Multipurpose, + + /// Fragment of Fragment Ack frame + FragOrFragAck, + + /// Extended frame + Extended, } impl TryWrite for FrameContent { @@ -408,8 +421,8 @@ impl TryWrite for FrameContent { let offset = &mut 0; match self { FrameContent::Beacon(beacon) => bytes.write(offset, beacon)?, - FrameContent::Data | FrameContent::Acknowledgement => (), FrameContent::Command(command) => bytes.write(offset, command)?, + _ => (), }; Ok(*offset) } @@ -426,6 +439,9 @@ impl TryRead<'_, &Header> for FrameContent { FrameType::MacCommand => { FrameContent::Command(bytes.read(offset)?) } + FrameType::Multipurpose => FrameContent::Multipurpose, + FrameType::FragOrFragAck => FrameContent::FragOrFragAck, + FrameType::Extended => FrameContent::Extended, }, *offset, )) @@ -434,6 +450,7 @@ impl TryRead<'_, &Header> for FrameContent { /// Signals an error that occured while decoding bytes #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum DecodeError { /// Buffer does not contain enough bytes NotEnoughBytes, @@ -503,6 +520,7 @@ impl From for byte::Error { /// Errors that can occur while securing or unsecuring a frame #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum EncodeError { /// Something went wrong while writing a frame's bytes to the destination WriteError, @@ -606,6 +624,8 @@ mod tests { fn encode_ver0_short() { let frame = Frame { header: Header { + ie_present: false, + seq_no_suppress: false, frame_type: FrameType::Data, frame_pending: false, ack_request: false, @@ -648,6 +668,8 @@ mod tests { fn encode_ver1_extended() { let frame = Frame { header: Header { + ie_present: false, + seq_no_suppress: false, frame_type: FrameType::Beacon, frame_pending: true, ack_request: false, @@ -703,6 +725,8 @@ mod tests { fn encode_ver0_pan_compress() { let frame = Frame { header: Header { + ie_present: false, + seq_no_suppress: false, frame_type: FrameType::Acknowledgement, frame_pending: false, ack_request: false, @@ -745,6 +769,8 @@ mod tests { fn encode_ver2_none() { let frame = Frame { header: Header { + ie_present: false, + seq_no_suppress: false, frame_type: FrameType::MacCommand, frame_pending: false, ack_request: true, diff --git a/src/mac/frame/security/auxiliary_security_header.rs b/src/mac/frame/security/auxiliary_security_header.rs index 98bb4c1..1e771f2 100644 --- a/src/mac/frame/security/auxiliary_security_header.rs +++ b/src/mac/frame/security/auxiliary_security_header.rs @@ -10,6 +10,7 @@ use cipher::{consts::U16, BlockCipher, NewBlockCipher}; /// /// See: section 7.4 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct AuxiliarySecurityHeader { /// The control field in the Auxiliary Security Header pub control: SecurityControl, @@ -154,6 +155,7 @@ where /// A key identifier #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct KeyIdentifier { /// The key source to be used for determining a key from this key identifier (if any) pub key_source: Option, @@ -180,6 +182,7 @@ impl TryWrite for KeyIdentifier { /// A key source #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum KeySource { /// A key source that is 4 octets long Short(u32), diff --git a/src/mac/frame/security/mod.rs b/src/mac/frame/security/mod.rs index bee9c8d..52d878f 100644 --- a/src/mac/frame/security/mod.rs +++ b/src/mac/frame/security/mod.rs @@ -109,6 +109,8 @@ //! let payload = &[0u8, 1u8, 2u8, 3u8, 4u8]; //! let frame_to_secure = Frame { //! header: Header { +//! ie_present: false, +//! seq_no_suppress: false, //! frame_type: FrameType::Data, //! frame_pending: false, //! ack_request: false, @@ -196,6 +198,7 @@ pub enum AddressingMode { } #[derive(Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] /// A partial device descriptor pub struct DeviceDescriptor { /// The frame counter associated with this device @@ -851,6 +854,8 @@ mod tests { ) -> Frame<'a> { Frame { header: Header { + ie_present: false, + seq_no_suppress: false, frame_type: FrameType::Data, frame_pending: false, ack_request: false, diff --git a/src/mac/frame/security/security_control.rs b/src/mac/frame/security/security_control.rs index 82cc9f0..dbca01b 100644 --- a/src/mac/frame/security/security_control.rs +++ b/src/mac/frame/security/security_control.rs @@ -7,6 +7,7 @@ use byte::{BytesExt, TryRead, TryWrite, LE}; /// /// Contains fields describing the security applied to the incoming frame #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SecurityControl { /// The security level applied to the incoming frame pub(crate) security_level: SecurityLevel, @@ -65,6 +66,7 @@ impl TryWrite for SecurityControl { /// The level of security applied to the payload #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum SecurityLevel { /// No encryption and no data authentication None = 0b000, @@ -126,6 +128,7 @@ impl SecurityLevel { /// The key identifier mode #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum KeyIdentifierMode { /// No key identifier None = 0b00, diff --git a/src/utils.rs b/src/utils.rs index 8806214..1225f73 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -15,6 +15,7 @@ macro_rules! extended_enum { $(#[$outer])* #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum $name { $( $(#[$inner])*