diff --git a/Cargo.toml b/Cargo.toml index 88e8f22..d7dabc9 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" } @@ -23,7 +25,9 @@ hash32-derive = "0.1" byte = "0.2.4" cipher = { version = "0.2", default-features = false } ccm = {version = "0.3.0", default-features = false} +defmt = { version = "0.2.1", optional = true } [dev-dependencies] aes-soft = {version = "0.6.4", default-features = false} rand = "0.8.3" + diff --git a/src/mac/beacon.rs b/src/mac/beacon.rs index 714a207..8f39996 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. /// @@ -150,6 +153,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, @@ -159,6 +163,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, @@ -228,6 +233,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, @@ -345,6 +351,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], @@ -429,6 +436,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 258d125..692871a 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. @@ -123,6 +124,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, @@ -183,6 +185,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, @@ -219,6 +222,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..1a2d2ea 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 b46588d..6a76c76 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, @@ -120,6 +127,9 @@ impl TryRead<'_> for Header { let ack_request = ((bits & mask::ACK) >> offset::ACK) as u8; 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; @@ -136,6 +146,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 */ @@ -189,6 +201,8 @@ impl TryRead<'_> for Header { frame_pending, ack_request, pan_id_compress, + seq_no_suppress, + ie_present, version, seq, destination, @@ -278,6 +292,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 { @@ -315,6 +330,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 { @@ -354,6 +370,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 { @@ -383,6 +400,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), @@ -391,6 +409,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 40c6f2b..14bc2d5 100644 --- a/src/mac/frame/mod.rs +++ b/src/mac/frame/mod.rs @@ -150,6 +150,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, @@ -367,6 +368,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, @@ -382,6 +384,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), @@ -391,6 +394,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 { @@ -398,8 +409,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) } @@ -414,6 +425,9 @@ impl TryRead<'_, &Header> for FrameContent { FrameType::Data => FrameContent::Data, FrameType::Acknowledgement => FrameContent::Acknowledgement, FrameType::MacCommand => FrameContent::Command(bytes.read(offset)?), + FrameType::Multipurpose => FrameContent::Multipurpose, + FrameType::FragOrFragAck => FrameContent::FragOrFragAck, + FrameType::Extended => FrameContent::Extended, }, *offset, )) @@ -422,6 +436,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, @@ -491,6 +506,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, diff --git a/src/mac/frame/security/auxiliary_security_header.rs b/src/mac/frame/security/auxiliary_security_header.rs index 8270db9..8c59916 100644 --- a/src/mac/frame/security/auxiliary_security_header.rs +++ b/src/mac/frame/security/auxiliary_security_header.rs @@ -8,6 +8,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, @@ -147,6 +148,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, @@ -173,6 +175,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 b10a00c..9554dab 100644 --- a/src/mac/frame/security/mod.rs +++ b/src/mac/frame/security/mod.rs @@ -191,6 +191,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 diff --git a/src/mac/frame/security/security_control.rs b/src/mac/frame/security/security_control.rs index 313c4ba..a77d000 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, @@ -63,6 +64,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, @@ -124,6 +126,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])*