Merge branch 'master' into mac
This commit is contained in:
		@@ -1,15 +1,16 @@
 | 
			
		||||
use core::{mem, slice};
 | 
			
		||||
 | 
			
		||||
use super::opcodes::OpcodeM4ToM0;
 | 
			
		||||
use super::typedefs::{
 | 
			
		||||
    AddressMode, Capabilities, DisassociationReason, GtsCharacteristics, KeyIdMode, MacAddress, MacChannel, MacStatus,
 | 
			
		||||
    PanId, PibId, ScanType, SecurityLevel,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
pub trait MacCommand {
 | 
			
		||||
pub trait MacCommand: Sized {
 | 
			
		||||
    const OPCODE: OpcodeM4ToM0;
 | 
			
		||||
    const SIZE: usize;
 | 
			
		||||
 | 
			
		||||
    fn copy_into_slice(&self, buf: &mut [u8]) {
 | 
			
		||||
        unsafe { core::ptr::copy(self as *const _ as *const u8, buf as *mut _ as *mut u8, Self::SIZE) };
 | 
			
		||||
    fn payload<'a>(&'a self) -> &'a [u8] {
 | 
			
		||||
        unsafe { slice::from_raw_parts(self as *const _ as *const u8, mem::size_of::<Self>()) }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -41,7 +42,6 @@ pub struct AssociateRequest {
 | 
			
		||||
 | 
			
		||||
impl MacCommand for AssociateRequest {
 | 
			
		||||
    const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeAssociateReq;
 | 
			
		||||
    const SIZE: usize = 25;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// MLME DISASSOCIATE Request sed to request a disassociation
 | 
			
		||||
@@ -70,20 +70,22 @@ pub struct DisassociateRequest {
 | 
			
		||||
 | 
			
		||||
impl MacCommand for DisassociateRequest {
 | 
			
		||||
    const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeDisassociateReq;
 | 
			
		||||
    const SIZE: usize = 24;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// MLME GET Request used to request a PIB value
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[derive(Default)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct GetRequest {
 | 
			
		||||
    /// the name of the PIB attribute to read
 | 
			
		||||
    pub pib_attribute: PibId,
 | 
			
		||||
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    pub a_stuffing: [u8; 3],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl MacCommand for GetRequest {
 | 
			
		||||
    const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeGetReq;
 | 
			
		||||
    const SIZE: usize = 4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// MLME GTS Request used to request and maintain GTSs
 | 
			
		||||
@@ -104,19 +106,20 @@ pub struct GtsRequest {
 | 
			
		||||
 | 
			
		||||
impl MacCommand for GtsRequest {
 | 
			
		||||
    const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeGetReq;
 | 
			
		||||
    const SIZE: usize = 12;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[derive(Default)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct ResetRequest {
 | 
			
		||||
    /// MAC PIB attributes are set to their default values or not during reset
 | 
			
		||||
    pub set_default_pib: bool,
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    pub a_stuffing: [u8; 3],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl MacCommand for ResetRequest {
 | 
			
		||||
    const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeResetReq;
 | 
			
		||||
    const SIZE: usize = 4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// MLME RX ENABLE Request used to request that the receiver is either enabled
 | 
			
		||||
@@ -129,6 +132,8 @@ pub struct RxEnableRequest {
 | 
			
		||||
    /// configure the transceiver to RX with ranging for a value of
 | 
			
		||||
    /// RANGING_ON or to not enable ranging for RANGING_OFF
 | 
			
		||||
    pub ranging_rx_control: u8,
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    pub a_stuffing: [u8; 2],
 | 
			
		||||
    /// number of symbols measured before the receiver is to be enabled or disabled
 | 
			
		||||
    pub rx_on_time: [u8; 4],
 | 
			
		||||
    /// number of symbols for which the receiver is to be enabled
 | 
			
		||||
@@ -137,19 +142,6 @@ pub struct RxEnableRequest {
 | 
			
		||||
 | 
			
		||||
impl MacCommand for RxEnableRequest {
 | 
			
		||||
    const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeRxEnableReq;
 | 
			
		||||
    const SIZE: usize = 12;
 | 
			
		||||
 | 
			
		||||
    fn copy_into_slice(&self, buf: &mut [u8]) {
 | 
			
		||||
        buf[0] = self.defer_permit as u8;
 | 
			
		||||
        buf[1] = self.ranging_rx_control as u8;
 | 
			
		||||
 | 
			
		||||
        // stuffing to keep 32bit alignment
 | 
			
		||||
        buf[2] = 0;
 | 
			
		||||
        buf[3] = 0;
 | 
			
		||||
 | 
			
		||||
        buf[4..8].copy_from_slice(&self.rx_on_time);
 | 
			
		||||
        buf[8..12].copy_from_slice(&self.rx_on_duration);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// MLME SCAN Request used to initiate a channel scan over a given list of channels
 | 
			
		||||
@@ -172,11 +164,12 @@ pub struct ScanRequest {
 | 
			
		||||
    pub key_id_mode: KeyIdMode,
 | 
			
		||||
    /// index of the key to be used
 | 
			
		||||
    pub key_index: u8,
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    pub a_stuffing: [u8; 2],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl MacCommand for ScanRequest {
 | 
			
		||||
    const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeScanReq;
 | 
			
		||||
    const SIZE: usize = 20;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// MLME SET Request used to attempt to write the given value to the indicated PIB attribute
 | 
			
		||||
@@ -191,13 +184,12 @@ pub struct SetRequest {
 | 
			
		||||
 | 
			
		||||
impl MacCommand for SetRequest {
 | 
			
		||||
    const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSetReq;
 | 
			
		||||
    const SIZE: usize = 8;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// MLME START Request used by the FFDs to intiate a new PAN or to begin using a new superframe
 | 
			
		||||
/// configuration
 | 
			
		||||
#[derive(Default)]
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[derive(Default)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct StartRequest {
 | 
			
		||||
    /// PAN indentifier to used by the device
 | 
			
		||||
@@ -236,7 +228,6 @@ pub struct StartRequest {
 | 
			
		||||
 | 
			
		||||
impl MacCommand for StartRequest {
 | 
			
		||||
    const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeStartReq;
 | 
			
		||||
    const SIZE: usize = 35;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// MLME SYNC Request used to synchronize with the coordinator by acquiring and, if
 | 
			
		||||
@@ -253,11 +244,12 @@ pub struct SyncRequest {
 | 
			
		||||
    ///
 | 
			
		||||
    /// `false` if the MLME is to synchronize with only the next beacon
 | 
			
		||||
    pub track_beacon: bool,
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    pub a_stuffing: [u8; 1],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl MacCommand for SyncRequest {
 | 
			
		||||
    const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSyncReq;
 | 
			
		||||
    const SIZE: usize = 4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// MLME POLL Request propmts the device to request data from the coordinator
 | 
			
		||||
@@ -278,11 +270,12 @@ pub struct PollRequest {
 | 
			
		||||
    pub key_source: [u8; 8],
 | 
			
		||||
    /// PAN identifier of the coordinator
 | 
			
		||||
    pub coord_pan_id: PanId,
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    pub a_stuffing: [u8; 2],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl MacCommand for PollRequest {
 | 
			
		||||
    const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmePollReq;
 | 
			
		||||
    const SIZE: usize = 24;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// MLME DPS Request allows the next higher layer to request that the PHY utilize a
 | 
			
		||||
@@ -297,33 +290,38 @@ pub struct DpsRequest {
 | 
			
		||||
    /// the number of symbols for which the transmitter and receiver will utilize the
 | 
			
		||||
    /// respective DPS indices
 | 
			
		||||
    dps_index_duration: u8,
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    pub a_stuffing: [u8; 1],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl MacCommand for DpsRequest {
 | 
			
		||||
    const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeDpsReq;
 | 
			
		||||
    const SIZE: usize = 4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// MLME SOUNDING request primitive which is used by the next higher layer to request that
 | 
			
		||||
/// the PHY respond with channel sounding information
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct SoundingRequest;
 | 
			
		||||
pub struct SoundingRequest {
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    pub a_stuffing: [u8; 4],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl MacCommand for SoundingRequest {
 | 
			
		||||
    const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSoundingReq;
 | 
			
		||||
    const SIZE: usize = 4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// MLME CALIBRATE request primitive which used  to obtain the results of a ranging
 | 
			
		||||
/// calibration request from an RDEV
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct CalibrateRequest;
 | 
			
		||||
pub struct CalibrateRequest {
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    pub a_stuffing: [u8; 4],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl MacCommand for CalibrateRequest {
 | 
			
		||||
    const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeCalibrateReq;
 | 
			
		||||
    const SIZE: usize = 4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// MCPS DATA Request used for MAC data related requests from the application
 | 
			
		||||
@@ -370,6 +368,15 @@ pub struct DataRequest {
 | 
			
		||||
    pub datrate: u8,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl DataRequest {
 | 
			
		||||
    pub fn set_buffer<'a>(&'a mut self, buf: &'a [u8]) -> &mut Self {
 | 
			
		||||
        self.msdu_ptr = buf as *const _ as *const u8;
 | 
			
		||||
        self.msdu_length = buf.len() as u8;
 | 
			
		||||
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Default for DataRequest {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
@@ -397,7 +404,6 @@ impl Default for DataRequest {
 | 
			
		||||
 | 
			
		||||
impl MacCommand for DataRequest {
 | 
			
		||||
    const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::McpsDataReq;
 | 
			
		||||
    const SIZE: usize = 40;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// for MCPS PURGE Request used to purge an MSDU from the transaction queue
 | 
			
		||||
@@ -407,11 +413,12 @@ pub struct PurgeRequest {
 | 
			
		||||
    /// the handle associated with the MSDU to be purged from the transaction
 | 
			
		||||
    /// queue
 | 
			
		||||
    pub msdu_handle: u8,
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    pub a_stuffing: [u8; 3],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl MacCommand for PurgeRequest {
 | 
			
		||||
    const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::McpsPurgeReq;
 | 
			
		||||
    const SIZE: usize = 4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// MLME ASSOCIATE Response used to initiate a response to an MLME-ASSOCIATE.indication
 | 
			
		||||
@@ -434,11 +441,12 @@ pub struct AssociateResponse {
 | 
			
		||||
    pub key_id_mode: KeyIdMode,
 | 
			
		||||
    /// the index of the key to be used
 | 
			
		||||
    pub key_index: u8,
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    pub a_stuffing: [u8; 2],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl MacCommand for AssociateResponse {
 | 
			
		||||
    const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeAssociateRes;
 | 
			
		||||
    const SIZE: usize = 24;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// MLME ORPHAN Response used to respond to the MLME ORPHAN Indication
 | 
			
		||||
@@ -459,9 +467,10 @@ pub struct OrphanResponse {
 | 
			
		||||
    pub key_id_mode: KeyIdMode,
 | 
			
		||||
    /// the index of the key to be used
 | 
			
		||||
    pub key_index: u8,
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    pub a_stuffing: [u8; 2],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl MacCommand for OrphanResponse {
 | 
			
		||||
    const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeOrphanRes;
 | 
			
		||||
    const SIZE: usize = 24;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,8 @@ use embassy_sync::blocking_mutex::raw::NoopRawMutex;
 | 
			
		||||
use embassy_sync::pubsub::{PubSubChannel, Subscriber};
 | 
			
		||||
 | 
			
		||||
use super::helpers::to_u16;
 | 
			
		||||
use core::mem;
 | 
			
		||||
 | 
			
		||||
use super::indications::{
 | 
			
		||||
    AssociateIndication, BeaconNotifyIndication, CommStatusIndication, DataIndication, DisassociateIndication,
 | 
			
		||||
    DpsIndication, GtsIndication, OrphanIndication, PollIndication, SyncLossIndication,
 | 
			
		||||
@@ -12,91 +14,100 @@ use super::responses::{
 | 
			
		||||
    AssociateConfirm, CalibrateConfirm, DataConfirm, DisassociateConfirm, DpsConfirm, GetConfirm, GtsConfirm,
 | 
			
		||||
    PollConfirm, PurgeConfirm, ResetConfirm, RxEnableConfirm, ScanConfirm, SetConfirm, SoundingConfirm, StartConfirm,
 | 
			
		||||
};
 | 
			
		||||
use crate::evt::EvtBox;
 | 
			
		||||
use crate::mac::opcodes::OpcodeM0ToM4;
 | 
			
		||||
use crate::sub::mac::Mac;
 | 
			
		||||
 | 
			
		||||
pub trait ParseableMacEvent {
 | 
			
		||||
    const SIZE: usize;
 | 
			
		||||
 | 
			
		||||
    fn validate(buf: &[u8]) -> Result<(), ()> {
 | 
			
		||||
        if buf.len() < Self::SIZE {
 | 
			
		||||
            return Err(());
 | 
			
		||||
pub(crate) trait ParseableMacEvent: Sized {
 | 
			
		||||
    fn from_buffer<'a>(buf: &'a [u8]) -> Result<&'a Self, ()> {
 | 
			
		||||
        if buf.len() < mem::size_of::<Self>() {
 | 
			
		||||
            Err(())
 | 
			
		||||
        } else {
 | 
			
		||||
            Ok(unsafe { &*(buf as *const _ as *const Self) })
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
        Ok(())
 | 
			
		||||
pub struct Event {
 | 
			
		||||
    event_box: EvtBox<Mac>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Event {
 | 
			
		||||
    pub(crate) fn new(event_box: EvtBox<Mac>) -> Self {
 | 
			
		||||
        Self { event_box }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()>
 | 
			
		||||
    where
 | 
			
		||||
        Self: Sized;
 | 
			
		||||
    pub fn mac_event<'a>(&'a self) -> Result<MacEvent<'a>, ()> {
 | 
			
		||||
        let payload = self.event_box.payload();
 | 
			
		||||
        let opcode = u16::from_le_bytes(payload[0..2].try_into().unwrap());
 | 
			
		||||
 | 
			
		||||
        let opcode = OpcodeM0ToM4::try_from(opcode)?;
 | 
			
		||||
        let buf = &payload[2..];
 | 
			
		||||
 | 
			
		||||
        match opcode {
 | 
			
		||||
            OpcodeM0ToM4::MlmeAssociateCnf => Ok(MacEvent::MlmeAssociateCnf(AssociateConfirm::from_buffer(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeDisassociateCnf => {
 | 
			
		||||
                Ok(MacEvent::MlmeDisassociateCnf(DisassociateConfirm::from_buffer(buf)?))
 | 
			
		||||
            }
 | 
			
		||||
            OpcodeM0ToM4::MlmeGetCnf => Ok(MacEvent::MlmeGetCnf(GetConfirm::from_buffer(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeGtsCnf => Ok(MacEvent::MlmeGtsCnf(GtsConfirm::from_buffer(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeResetCnf => Ok(MacEvent::MlmeResetCnf(ResetConfirm::from_buffer(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeRxEnableCnf => Ok(MacEvent::MlmeRxEnableCnf(RxEnableConfirm::from_buffer(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeScanCnf => Ok(MacEvent::MlmeScanCnf(ScanConfirm::from_buffer(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeSetCnf => Ok(MacEvent::MlmeSetCnf(SetConfirm::from_buffer(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeStartCnf => Ok(MacEvent::MlmeStartCnf(StartConfirm::from_buffer(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmePollCnf => Ok(MacEvent::MlmePollCnf(PollConfirm::from_buffer(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeDpsCnf => Ok(MacEvent::MlmeDpsCnf(DpsConfirm::from_buffer(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeSoundingCnf => Ok(MacEvent::MlmeSoundingCnf(SoundingConfirm::from_buffer(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeCalibrateCnf => Ok(MacEvent::MlmeCalibrateCnf(CalibrateConfirm::from_buffer(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::McpsDataCnf => Ok(MacEvent::McpsDataCnf(DataConfirm::from_buffer(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::McpsPurgeCnf => Ok(MacEvent::McpsPurgeCnf(PurgeConfirm::from_buffer(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeAssociateInd => Ok(MacEvent::MlmeAssociateInd(AssociateIndication::from_buffer(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeDisassociateInd => {
 | 
			
		||||
                Ok(MacEvent::MlmeDisassociateInd(DisassociateIndication::from_buffer(buf)?))
 | 
			
		||||
            }
 | 
			
		||||
            OpcodeM0ToM4::MlmeBeaconNotifyInd => {
 | 
			
		||||
                Ok(MacEvent::MlmeBeaconNotifyInd(BeaconNotifyIndication::from_buffer(buf)?))
 | 
			
		||||
            }
 | 
			
		||||
            OpcodeM0ToM4::MlmeCommStatusInd => Ok(MacEvent::MlmeCommStatusInd(CommStatusIndication::from_buffer(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeGtsInd => Ok(MacEvent::MlmeGtsInd(GtsIndication::from_buffer(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeOrphanInd => Ok(MacEvent::MlmeOrphanInd(OrphanIndication::from_buffer(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeSyncLossInd => Ok(MacEvent::MlmeSyncLossInd(SyncLossIndication::from_buffer(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeDpsInd => Ok(MacEvent::MlmeDpsInd(DpsIndication::from_buffer(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::McpsDataInd => Ok(MacEvent::McpsDataInd(DataIndication::from_buffer(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmePollInd => Ok(MacEvent::MlmePollInd(PollIndication::from_buffer(buf)?)),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, PartialEq, Eq)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub enum MacEvent {
 | 
			
		||||
    MlmeAssociateCnf(AssociateConfirm),
 | 
			
		||||
    MlmeDisassociateCnf(DisassociateConfirm),
 | 
			
		||||
    MlmeGetCnf(GetConfirm),
 | 
			
		||||
    MlmeGtsCnf(GtsConfirm),
 | 
			
		||||
    MlmeResetCnf(ResetConfirm),
 | 
			
		||||
    MlmeRxEnableCnf(RxEnableConfirm),
 | 
			
		||||
    MlmeScanCnf(ScanConfirm),
 | 
			
		||||
    MlmeSetCnf(SetConfirm),
 | 
			
		||||
    MlmeStartCnf(StartConfirm),
 | 
			
		||||
    MlmePollCnf(PollConfirm),
 | 
			
		||||
    MlmeDpsCnf(DpsConfirm),
 | 
			
		||||
    MlmeSoundingCnf(SoundingConfirm),
 | 
			
		||||
    MlmeCalibrateCnf(CalibrateConfirm),
 | 
			
		||||
    McpsDataCnf(DataConfirm),
 | 
			
		||||
    McpsPurgeCnf(PurgeConfirm),
 | 
			
		||||
    MlmeAssociateInd(AssociateIndication),
 | 
			
		||||
    MlmeDisassociateInd(DisassociateIndication),
 | 
			
		||||
    MlmeBeaconNotifyInd(BeaconNotifyIndication),
 | 
			
		||||
    MlmeCommStatusInd(CommStatusIndication),
 | 
			
		||||
    MlmeGtsInd(GtsIndication),
 | 
			
		||||
    MlmeOrphanInd(OrphanIndication),
 | 
			
		||||
    MlmeSyncLossInd(SyncLossIndication),
 | 
			
		||||
    MlmeDpsInd(DpsIndication),
 | 
			
		||||
    McpsDataInd(DataIndication),
 | 
			
		||||
    MlmePollInd(PollIndication),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl TryFrom<&[u8]> for MacEvent {
 | 
			
		||||
    type Error = ();
 | 
			
		||||
 | 
			
		||||
    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
 | 
			
		||||
        let opcode = to_u16(&value[0..2]);
 | 
			
		||||
        let opcode = OpcodeM0ToM4::try_from(opcode)?;
 | 
			
		||||
 | 
			
		||||
        let buf = &value[2..];
 | 
			
		||||
 | 
			
		||||
        match opcode {
 | 
			
		||||
            OpcodeM0ToM4::MlmeAssociateCnf => Ok(Self::MlmeAssociateCnf(AssociateConfirm::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeDisassociateCnf => Ok(Self::MlmeDisassociateCnf(DisassociateConfirm::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeGetCnf => Ok(Self::MlmeGetCnf(GetConfirm::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeGtsCnf => Ok(Self::MlmeGtsCnf(GtsConfirm::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeResetCnf => Ok(Self::MlmeResetCnf(ResetConfirm::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeRxEnableCnf => Ok(Self::MlmeRxEnableCnf(RxEnableConfirm::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeScanCnf => Ok(Self::MlmeScanCnf(ScanConfirm::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeSetCnf => Ok(Self::MlmeSetCnf(SetConfirm::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeStartCnf => Ok(Self::MlmeStartCnf(StartConfirm::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmePollCnf => Ok(Self::MlmePollCnf(PollConfirm::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeDpsCnf => Ok(Self::MlmeDpsCnf(DpsConfirm::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeSoundingCnf => Ok(Self::MlmeSoundingCnf(SoundingConfirm::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeCalibrateCnf => Ok(Self::MlmeCalibrateCnf(CalibrateConfirm::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::McpsDataCnf => Ok(Self::McpsDataCnf(DataConfirm::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::McpsPurgeCnf => Ok(Self::McpsPurgeCnf(PurgeConfirm::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeAssociateInd => Ok(Self::MlmeAssociateInd(AssociateIndication::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeDisassociateInd => Ok(Self::MlmeDisassociateInd(DisassociateIndication::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeBeaconNotifyInd => Ok(Self::MlmeBeaconNotifyInd(BeaconNotifyIndication::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeCommStatusInd => Ok(Self::MlmeCommStatusInd(CommStatusIndication::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeGtsInd => Ok(Self::MlmeGtsInd(GtsIndication::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeOrphanInd => Ok(Self::MlmeOrphanInd(OrphanIndication::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeSyncLossInd => Ok(Self::MlmeSyncLossInd(SyncLossIndication::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmeDpsInd => Ok(Self::MlmeDpsInd(DpsIndication::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::McpsDataInd => Ok(Self::McpsDataInd(DataIndication::try_parse(buf)?)),
 | 
			
		||||
            OpcodeM0ToM4::MlmePollInd => Ok(Self::MlmePollInd(PollIndication::try_parse(buf)?)),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
pub enum MacEvent<'a> {
 | 
			
		||||
    MlmeAssociateCnf(&'a AssociateConfirm),
 | 
			
		||||
    MlmeDisassociateCnf(&'a DisassociateConfirm),
 | 
			
		||||
    MlmeGetCnf(&'a GetConfirm),
 | 
			
		||||
    MlmeGtsCnf(&'a GtsConfirm),
 | 
			
		||||
    MlmeResetCnf(&'a ResetConfirm),
 | 
			
		||||
    MlmeRxEnableCnf(&'a RxEnableConfirm),
 | 
			
		||||
    MlmeScanCnf(&'a ScanConfirm),
 | 
			
		||||
    MlmeSetCnf(&'a SetConfirm),
 | 
			
		||||
    MlmeStartCnf(&'a StartConfirm),
 | 
			
		||||
    MlmePollCnf(&'a PollConfirm),
 | 
			
		||||
    MlmeDpsCnf(&'a DpsConfirm),
 | 
			
		||||
    MlmeSoundingCnf(&'a SoundingConfirm),
 | 
			
		||||
    MlmeCalibrateCnf(&'a CalibrateConfirm),
 | 
			
		||||
    McpsDataCnf(&'a DataConfirm),
 | 
			
		||||
    McpsPurgeCnf(&'a PurgeConfirm),
 | 
			
		||||
    MlmeAssociateInd(&'a AssociateIndication),
 | 
			
		||||
    MlmeDisassociateInd(&'a DisassociateIndication),
 | 
			
		||||
    MlmeBeaconNotifyInd(&'a BeaconNotifyIndication),
 | 
			
		||||
    MlmeCommStatusInd(&'a CommStatusIndication),
 | 
			
		||||
    MlmeGtsInd(&'a GtsIndication),
 | 
			
		||||
    MlmeOrphanInd(&'a OrphanIndication),
 | 
			
		||||
    MlmeSyncLossInd(&'a SyncLossIndication),
 | 
			
		||||
    MlmeDpsInd(&'a DpsIndication),
 | 
			
		||||
    McpsDataInd(&'a DataIndication),
 | 
			
		||||
    MlmePollInd(&'a PollIndication),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO this PubSub can probably be replaced with shared memory to make it a bit more efficient.
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +0,0 @@
 | 
			
		||||
pub fn to_u16(buf: &[u8]) -> u16 {
 | 
			
		||||
    ((buf[1] as u16) << 8) | buf[0] as u16
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn to_u32(buf: &[u8]) -> u32 {
 | 
			
		||||
    ((buf[0] as u32) << 0) + ((buf[1] as u32) << 8) + ((buf[2] as u32) << 16) + ((buf[3] as u32) << 24)
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
use core::slice;
 | 
			
		||||
 | 
			
		||||
use super::consts::MAX_PENDING_ADDRESS;
 | 
			
		||||
use super::event::ParseableMacEvent;
 | 
			
		||||
use super::helpers::to_u32;
 | 
			
		||||
use super::typedefs::{
 | 
			
		||||
    AddressMode, Capabilities, DisassociationReason, KeyIdMode, MacAddress, MacChannel, MacStatus, PanDescriptor,
 | 
			
		||||
    PanId, SecurityLevel,
 | 
			
		||||
@@ -8,6 +9,7 @@ use super::typedefs::{
 | 
			
		||||
 | 
			
		||||
/// MLME ASSOCIATE Indication which will be used by the MAC
 | 
			
		||||
/// to indicate the reception of an association request command
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct AssociateIndication {
 | 
			
		||||
    /// Extended address of the device requesting association
 | 
			
		||||
@@ -24,25 +26,11 @@ pub struct AssociateIndication {
 | 
			
		||||
    pub key_source: [u8; 8],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for AssociateIndication {
 | 
			
		||||
    const SIZE: usize = 20;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            device_address: [buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]],
 | 
			
		||||
            capability_information: Capabilities::from_bits(buf[8]).ok_or(())?,
 | 
			
		||||
            security_level: SecurityLevel::try_from(buf[9])?,
 | 
			
		||||
            key_id_mode: KeyIdMode::try_from(buf[10])?,
 | 
			
		||||
            key_index: buf[11],
 | 
			
		||||
            key_source: [buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19]],
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ParseableMacEvent for AssociateIndication {}
 | 
			
		||||
 | 
			
		||||
/// MLME DISASSOCIATE indication which will be used to send
 | 
			
		||||
/// disassociation indication to the application.
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct DisassociateIndication {
 | 
			
		||||
    /// Extended address of the device requesting association
 | 
			
		||||
@@ -59,25 +47,11 @@ pub struct DisassociateIndication {
 | 
			
		||||
    pub key_source: [u8; 8],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for DisassociateIndication {
 | 
			
		||||
    const SIZE: usize = 20;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            device_address: [buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]],
 | 
			
		||||
            disassociation_reason: DisassociationReason::try_from(buf[8])?,
 | 
			
		||||
            security_level: SecurityLevel::try_from(buf[9])?,
 | 
			
		||||
            key_id_mode: KeyIdMode::try_from(buf[10])?,
 | 
			
		||||
            key_index: buf[11],
 | 
			
		||||
            key_source: [buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19]],
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ParseableMacEvent for DisassociateIndication {}
 | 
			
		||||
 | 
			
		||||
/// MLME BEACON NOTIIFY Indication which is used to send parameters contained
 | 
			
		||||
/// within a beacon frame received by the MAC to the application
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct BeaconNotifyIndication {
 | 
			
		||||
    /// he set of octets comprising the beacon payload to be transferred
 | 
			
		||||
@@ -95,36 +69,10 @@ pub struct BeaconNotifyIndication {
 | 
			
		||||
    pub sdu_length: u8,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for BeaconNotifyIndication {
 | 
			
		||||
    const SIZE: usize = 88;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        // TODO: this is unchecked
 | 
			
		||||
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        let addr_list = [
 | 
			
		||||
            MacAddress::try_from(&buf[26..34])?,
 | 
			
		||||
            MacAddress::try_from(&buf[34..42])?,
 | 
			
		||||
            MacAddress::try_from(&buf[42..50])?,
 | 
			
		||||
            MacAddress::try_from(&buf[50..58])?,
 | 
			
		||||
            MacAddress::try_from(&buf[58..66])?,
 | 
			
		||||
            MacAddress::try_from(&buf[66..74])?,
 | 
			
		||||
            MacAddress::try_from(&buf[74..82])?,
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            sdu_ptr: to_u32(&buf[0..4]) as *const u8,
 | 
			
		||||
            pan_descriptor: PanDescriptor::try_from(&buf[4..26])?,
 | 
			
		||||
            addr_list,
 | 
			
		||||
            bsn: buf[82],
 | 
			
		||||
            pend_addr_spec: buf[83],
 | 
			
		||||
            sdu_length: buf[83],
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ParseableMacEvent for BeaconNotifyIndication {}
 | 
			
		||||
 | 
			
		||||
/// MLME COMM STATUS Indication which is used by the MAC to indicate a communications status
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct CommStatusIndication {
 | 
			
		||||
    /// The 16-bit PAN identifier of the device from which the frame
 | 
			
		||||
@@ -150,54 +98,11 @@ pub struct CommStatusIndication {
 | 
			
		||||
    pub key_source: [u8; 8],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for CommStatusIndication {
 | 
			
		||||
    const SIZE: usize = 32;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        let src_addr_mode = AddressMode::try_from(buf[2])?;
 | 
			
		||||
        let dst_addr_mode = AddressMode::try_from(buf[3])?;
 | 
			
		||||
 | 
			
		||||
        let src_address = match src_addr_mode {
 | 
			
		||||
            AddressMode::NoAddress => MacAddress { short: [0, 0] },
 | 
			
		||||
            AddressMode::Reserved => MacAddress { short: [0, 0] },
 | 
			
		||||
            AddressMode::Short => MacAddress {
 | 
			
		||||
                short: [buf[4], buf[5]],
 | 
			
		||||
            },
 | 
			
		||||
            AddressMode::Extended => MacAddress {
 | 
			
		||||
                extended: [buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]],
 | 
			
		||||
            },
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let dst_address = match dst_addr_mode {
 | 
			
		||||
            AddressMode::NoAddress => MacAddress { short: [0, 0] },
 | 
			
		||||
            AddressMode::Reserved => MacAddress { short: [0, 0] },
 | 
			
		||||
            AddressMode::Short => MacAddress {
 | 
			
		||||
                short: [buf[12], buf[13]],
 | 
			
		||||
            },
 | 
			
		||||
            AddressMode::Extended => MacAddress {
 | 
			
		||||
                extended: [buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19]],
 | 
			
		||||
            },
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            pan_id: PanId([buf[0], buf[1]]),
 | 
			
		||||
            src_addr_mode,
 | 
			
		||||
            dst_addr_mode,
 | 
			
		||||
            src_address,
 | 
			
		||||
            dst_address,
 | 
			
		||||
            status: MacStatus::try_from(buf[20])?,
 | 
			
		||||
            security_level: SecurityLevel::try_from(buf[21])?,
 | 
			
		||||
            key_id_mode: KeyIdMode::try_from(buf[22])?,
 | 
			
		||||
            key_index: buf[23],
 | 
			
		||||
            key_source: [buf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31]],
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ParseableMacEvent for CommStatusIndication {}
 | 
			
		||||
 | 
			
		||||
/// MLME GTS Indication indicates that a GTS has been allocated or that a
 | 
			
		||||
/// previously allocated GTS has been deallocated
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct GtsIndication {
 | 
			
		||||
    /// The short address of the device that has been allocated or deallocated a GTS
 | 
			
		||||
@@ -210,30 +115,17 @@ pub struct GtsIndication {
 | 
			
		||||
    pub key_id_mode: KeyIdMode,
 | 
			
		||||
    /// Index of the key to be used
 | 
			
		||||
    pub key_index: u8,
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    a_stuffing: [u8; 2],
 | 
			
		||||
    /// Originator of the key to be used
 | 
			
		||||
    pub key_source: [u8; 8],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for GtsIndication {
 | 
			
		||||
    const SIZE: usize = 16;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            device_address: [buf[0], buf[1]],
 | 
			
		||||
            gts_characteristics: buf[2],
 | 
			
		||||
            security_level: SecurityLevel::try_from(buf[3])?,
 | 
			
		||||
            key_id_mode: KeyIdMode::try_from(buf[4])?,
 | 
			
		||||
            key_index: buf[5],
 | 
			
		||||
            // 2 byte stuffing
 | 
			
		||||
            key_source: [buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]],
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ParseableMacEvent for GtsIndication {}
 | 
			
		||||
 | 
			
		||||
/// MLME ORPHAN Indication which is used by the coordinator to notify the
 | 
			
		||||
/// application of the presence of an orphaned device
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct OrphanIndication {
 | 
			
		||||
    /// Extended address of the orphaned device
 | 
			
		||||
@@ -246,27 +138,15 @@ pub struct OrphanIndication {
 | 
			
		||||
    pub key_id_mode: KeyIdMode,
 | 
			
		||||
    /// Index of the key used by the originator of the received frame
 | 
			
		||||
    pub key_index: u8,
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    a_stuffing: [u8; 1],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for OrphanIndication {
 | 
			
		||||
    const SIZE: usize = 20;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            orphan_address: [buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]],
 | 
			
		||||
            key_source: [buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]],
 | 
			
		||||
            security_level: SecurityLevel::try_from(buf[16])?,
 | 
			
		||||
            key_id_mode: KeyIdMode::try_from(buf[17])?,
 | 
			
		||||
            key_index: buf[18],
 | 
			
		||||
            // 1 byte stuffing
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ParseableMacEvent for OrphanIndication {}
 | 
			
		||||
 | 
			
		||||
/// MLME SYNC LOSS Indication which is used by the MAC to indicate the loss
 | 
			
		||||
/// of synchronization with the coordinator
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct SyncLossIndication {
 | 
			
		||||
    /// The PAN identifier with which the device lost synchronization or to which it was realigned
 | 
			
		||||
@@ -287,42 +167,21 @@ pub struct SyncLossIndication {
 | 
			
		||||
    pub key_source: [u8; 8],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for SyncLossIndication {
 | 
			
		||||
    const SIZE: usize = 16;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            pan_id: PanId([buf[0], buf[1]]),
 | 
			
		||||
            loss_reason: buf[2],
 | 
			
		||||
            channel_number: MacChannel::try_from(buf[3])?,
 | 
			
		||||
            channel_page: buf[4],
 | 
			
		||||
            security_level: SecurityLevel::try_from(buf[5])?,
 | 
			
		||||
            key_id_mode: KeyIdMode::try_from(buf[6])?,
 | 
			
		||||
            key_index: buf[7],
 | 
			
		||||
            key_source: [buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]],
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ParseableMacEvent for SyncLossIndication {}
 | 
			
		||||
 | 
			
		||||
/// MLME DPS Indication which indicates the expiration of the DPSIndexDuration
 | 
			
		||||
///  and the resetting of the DPS values in the PHY
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct DpsIndication;
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for DpsIndication {
 | 
			
		||||
    const SIZE: usize = 4;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        Ok(Self)
 | 
			
		||||
    }
 | 
			
		||||
pub struct DpsIndication {
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    a_stuffing: [u8; 4],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for DpsIndication {}
 | 
			
		||||
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
#[repr(C, align(8))]
 | 
			
		||||
pub struct DataIndication {
 | 
			
		||||
    /// Pointer to the set of octets forming the MSDU being indicated  
 | 
			
		||||
    pub msdu_ptr: *const u8,
 | 
			
		||||
@@ -347,9 +206,9 @@ pub struct DataIndication {
 | 
			
		||||
    /// The time, in symbols, at which the data were received  
 | 
			
		||||
    pub time_stamp: [u8; 4],
 | 
			
		||||
    /// The security level purportedly used by the received data frame  
 | 
			
		||||
    pub security_level: SecurityLevel,
 | 
			
		||||
    security_level: SecurityLevel,
 | 
			
		||||
    /// Mode used to identify the key used by originator of received frame  
 | 
			
		||||
    pub key_id_mode: KeyIdMode,
 | 
			
		||||
    key_id_mode: KeyIdMode,
 | 
			
		||||
    /// The originator of the key  
 | 
			
		||||
    pub key_source: [u8; 8],
 | 
			
		||||
    /// The index of the key  
 | 
			
		||||
@@ -374,68 +233,17 @@ pub struct DataIndication {
 | 
			
		||||
    pub rssi: u8,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for DataIndication {
 | 
			
		||||
    const SIZE: usize = 68;
 | 
			
		||||
impl ParseableMacEvent for DataIndication {}
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        let src_addr_mode = AddressMode::try_from(buf[4])?;
 | 
			
		||||
        let src_address = match src_addr_mode {
 | 
			
		||||
            AddressMode::NoAddress => MacAddress { short: [0, 0] },
 | 
			
		||||
            AddressMode::Reserved => MacAddress { short: [0, 0] },
 | 
			
		||||
            AddressMode::Short => MacAddress {
 | 
			
		||||
                short: [buf[7], buf[8]],
 | 
			
		||||
            },
 | 
			
		||||
            AddressMode::Extended => MacAddress {
 | 
			
		||||
                extended: [buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14]],
 | 
			
		||||
            },
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let dst_addr_mode = AddressMode::try_from(buf[15])?;
 | 
			
		||||
        let dst_address = match dst_addr_mode {
 | 
			
		||||
            AddressMode::NoAddress => MacAddress { short: [0, 0] },
 | 
			
		||||
            AddressMode::Reserved => MacAddress { short: [0, 0] },
 | 
			
		||||
            AddressMode::Short => MacAddress {
 | 
			
		||||
                short: [buf[18], buf[19]],
 | 
			
		||||
            },
 | 
			
		||||
            AddressMode::Extended => MacAddress {
 | 
			
		||||
                extended: [buf[18], buf[19], buf[20], buf[21], buf[22], buf[23], buf[24], buf[25]],
 | 
			
		||||
            },
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            msdu_ptr: to_u32(&buf[0..4]) as *const u8,
 | 
			
		||||
            src_addr_mode,
 | 
			
		||||
            src_pan_id: PanId([buf[5], buf[6]]),
 | 
			
		||||
            src_address,
 | 
			
		||||
            dst_addr_mode,
 | 
			
		||||
            dst_pan_id: PanId([buf[16], buf[17]]),
 | 
			
		||||
            dst_address,
 | 
			
		||||
            msdu_length: buf[26],
 | 
			
		||||
            mpdu_link_quality: buf[27],
 | 
			
		||||
            dsn: buf[28],
 | 
			
		||||
            time_stamp: [buf[29], buf[30], buf[31], buf[32]],
 | 
			
		||||
            security_level: SecurityLevel::try_from(buf[33]).unwrap_or(SecurityLevel::Unsecure), // TODO: this is totaly wrong, but I'm too smol brain to fix it
 | 
			
		||||
            key_id_mode: KeyIdMode::try_from(buf[34]).unwrap_or(KeyIdMode::Implicite), // TODO: this is totaly wrong, but I'm too smol brain to fix it
 | 
			
		||||
            key_source: [buf[35], buf[36], buf[37], buf[38], buf[39], buf[40], buf[41], buf[42]],
 | 
			
		||||
            key_index: buf[43],
 | 
			
		||||
            uwbprf: buf[44],
 | 
			
		||||
            uwn_preamble_symbol_repetitions: buf[45],
 | 
			
		||||
            datrate: buf[46],
 | 
			
		||||
            ranging_received: buf[47],
 | 
			
		||||
            ranging_counter_start: to_u32(&buf[48..52]),
 | 
			
		||||
            ranging_counter_stop: to_u32(&buf[52..56]),
 | 
			
		||||
            ranging_tracking_interval: to_u32(&buf[56..60]),
 | 
			
		||||
            ranging_offset: to_u32(&buf[60..64]),
 | 
			
		||||
            ranging_fom: buf[65],
 | 
			
		||||
            rssi: buf[66],
 | 
			
		||||
        })
 | 
			
		||||
impl DataIndication {
 | 
			
		||||
    pub fn payload<'a>(&'a self) -> &'a [u8] {
 | 
			
		||||
        unsafe { slice::from_raw_parts(self.msdu_ptr, self.msdu_length as usize) }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// MLME POLL Indication which will be used for indicating the Data Request
 | 
			
		||||
/// reception to upper layer as defined in Zigbee r22 - D.8.2
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct PollIndication {
 | 
			
		||||
    /// addressing mode used
 | 
			
		||||
@@ -444,27 +252,4 @@ pub struct PollIndication {
 | 
			
		||||
    pub request_address: MacAddress,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for PollIndication {
 | 
			
		||||
    const SIZE: usize = 9;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        let addr_mode = AddressMode::try_from(buf[0])?;
 | 
			
		||||
        let request_address = match addr_mode {
 | 
			
		||||
            AddressMode::NoAddress => MacAddress { short: [0, 0] },
 | 
			
		||||
            AddressMode::Reserved => MacAddress { short: [0, 0] },
 | 
			
		||||
            AddressMode::Short => MacAddress {
 | 
			
		||||
                short: [buf[1], buf[2]],
 | 
			
		||||
            },
 | 
			
		||||
            AddressMode::Extended => MacAddress {
 | 
			
		||||
                extended: [buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8]],
 | 
			
		||||
            },
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            addr_mode,
 | 
			
		||||
            request_address,
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ParseableMacEvent for PollIndication {}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,6 @@ pub mod commands;
 | 
			
		||||
mod consts;
 | 
			
		||||
pub mod control;
 | 
			
		||||
pub mod event;
 | 
			
		||||
mod helpers;
 | 
			
		||||
pub mod indications;
 | 
			
		||||
mod ioctl;
 | 
			
		||||
mod macros;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
use super::consts::{MAX_ED_SCAN_RESULTS_SUPPORTED, MAX_PAN_DESC_SUPPORTED, MAX_SOUNDING_LIST_SUPPORTED};
 | 
			
		||||
use super::event::ParseableMacEvent;
 | 
			
		||||
use super::helpers::to_u32;
 | 
			
		||||
use super::typedefs::{
 | 
			
		||||
    AddressMode, AssociationStatus, KeyIdMode, MacAddress, MacStatus, PanDescriptor, PanId, PibId, ScanType,
 | 
			
		||||
    SecurityLevel,
 | 
			
		||||
@@ -8,6 +7,7 @@ use super::typedefs::{
 | 
			
		||||
 | 
			
		||||
/// MLME ASSOCIATE Confirm used to inform of the initiating device whether
 | 
			
		||||
/// its request to associate was successful or unsuccessful
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct AssociateConfirm {
 | 
			
		||||
    /// short address allocated by the coordinator on successful association
 | 
			
		||||
@@ -22,26 +22,14 @@ pub struct AssociateConfirm {
 | 
			
		||||
    pub key_id_mode: KeyIdMode,
 | 
			
		||||
    /// the index of the key to be used
 | 
			
		||||
    pub key_index: u8,
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    a_stuffing: [u8; 2],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for AssociateConfirm {
 | 
			
		||||
    const SIZE: usize = 16;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            assoc_short_address: [buf[0], buf[1]],
 | 
			
		||||
            status: AssociationStatus::try_from(buf[2])?,
 | 
			
		||||
            security_level: SecurityLevel::try_from(buf[3])?,
 | 
			
		||||
            key_source: [buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]],
 | 
			
		||||
            key_id_mode: KeyIdMode::try_from(buf[12])?,
 | 
			
		||||
            key_index: buf[13],
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ParseableMacEvent for AssociateConfirm {}
 | 
			
		||||
 | 
			
		||||
/// MLME DISASSOCIATE Confirm used to send disassociation Confirmation to the application.
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct DisassociateConfirm {
 | 
			
		||||
    /// status of the disassociation attempt
 | 
			
		||||
@@ -54,34 +42,10 @@ pub struct DisassociateConfirm {
 | 
			
		||||
    pub device_address: MacAddress,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for DisassociateConfirm {
 | 
			
		||||
    const SIZE: usize = 12;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        let device_addr_mode = AddressMode::try_from(buf[1])?;
 | 
			
		||||
        let device_address = match device_addr_mode {
 | 
			
		||||
            AddressMode::NoAddress => MacAddress { short: [0, 0] },
 | 
			
		||||
            AddressMode::Reserved => MacAddress { short: [0, 0] },
 | 
			
		||||
            AddressMode::Short => MacAddress {
 | 
			
		||||
                short: [buf[4], buf[5]],
 | 
			
		||||
            },
 | 
			
		||||
            AddressMode::Extended => MacAddress {
 | 
			
		||||
                extended: [buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]],
 | 
			
		||||
            },
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            status: MacStatus::try_from(buf[0])?,
 | 
			
		||||
            device_addr_mode,
 | 
			
		||||
            device_pan_id: PanId([buf[2], buf[3]]),
 | 
			
		||||
            device_address,
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ParseableMacEvent for DisassociateConfirm {}
 | 
			
		||||
 | 
			
		||||
///  MLME GET Confirm which requests information about a given PIB attribute
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct GetConfirm {
 | 
			
		||||
    /// The pointer to the value of the PIB attribute attempted to read
 | 
			
		||||
@@ -92,88 +56,54 @@ pub struct GetConfirm {
 | 
			
		||||
    pub pib_attribute: PibId,
 | 
			
		||||
    /// The lenght of the PIB attribute Value return
 | 
			
		||||
    pub pib_attribute_value_len: u8,
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    a_stuffing: [u8; 1],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for GetConfirm {
 | 
			
		||||
    const SIZE: usize = 8;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        let address = to_u32(&buf[0..4]);
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            pib_attribute_value_ptr: address as *const u8,
 | 
			
		||||
            status: MacStatus::try_from(buf[4])?,
 | 
			
		||||
            pib_attribute: PibId::try_from(buf[5])?,
 | 
			
		||||
            pib_attribute_value_len: buf[6],
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ParseableMacEvent for GetConfirm {}
 | 
			
		||||
 | 
			
		||||
/// MLME GTS Confirm which eports the results of a request to allocate a new GTS
 | 
			
		||||
/// or to deallocate an existing GTS
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct GtsConfirm {
 | 
			
		||||
    /// The characteristics of the GTS
 | 
			
		||||
    pub gts_characteristics: u8,
 | 
			
		||||
    /// The status of the GTS reques
 | 
			
		||||
    pub status: MacStatus,
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    a_stuffing: [u8; 2],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for GtsConfirm {
 | 
			
		||||
    const SIZE: usize = 4;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            gts_characteristics: buf[0],
 | 
			
		||||
            status: MacStatus::try_from(buf[1])?,
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ParseableMacEvent for GtsConfirm {}
 | 
			
		||||
 | 
			
		||||
/// MLME RESET Confirm which is used to report the results of the reset operation
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct ResetConfirm {
 | 
			
		||||
    /// The result of the reset operation
 | 
			
		||||
    status: MacStatus,
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    a_stuffing: [u8; 3],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for ResetConfirm {
 | 
			
		||||
    const SIZE: usize = 4;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            status: MacStatus::try_from(buf[0])?,
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ParseableMacEvent for ResetConfirm {}
 | 
			
		||||
 | 
			
		||||
/// MLME RX ENABLE Confirm which is used to report the results of the attempt
 | 
			
		||||
/// to enable or disable the receiver
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct RxEnableConfirm {
 | 
			
		||||
    /// Result of the request to enable or disable the receiver
 | 
			
		||||
    status: MacStatus,
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    a_stuffing: [u8; 3],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for RxEnableConfirm {
 | 
			
		||||
    const SIZE: usize = 4;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            status: MacStatus::try_from(buf[0])?,
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ParseableMacEvent for RxEnableConfirm {}
 | 
			
		||||
 | 
			
		||||
/// MLME SCAN Confirm which is used to report the result of the channel scan request
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct ScanConfirm {
 | 
			
		||||
    /// Status of the scan request
 | 
			
		||||
@@ -196,150 +126,81 @@ pub struct ScanConfirm {
 | 
			
		||||
    pub uwb_energy_detect_list: [u8; MAX_ED_SCAN_RESULTS_SUPPORTED],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for ScanConfirm {
 | 
			
		||||
    const SIZE: usize = 185;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        // TODO: this is unchecked
 | 
			
		||||
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        let mut energy_detect_list = [0; MAX_ED_SCAN_RESULTS_SUPPORTED];
 | 
			
		||||
        energy_detect_list.copy_from_slice(&buf[8..24]);
 | 
			
		||||
 | 
			
		||||
        let pan_descriptor_list = [
 | 
			
		||||
            PanDescriptor::try_from(&buf[24..46])?,
 | 
			
		||||
            PanDescriptor::try_from(&buf[46..68])?,
 | 
			
		||||
            PanDescriptor::try_from(&buf[68..90])?,
 | 
			
		||||
            PanDescriptor::try_from(&buf[90..102])?,
 | 
			
		||||
            PanDescriptor::try_from(&buf[102..124])?,
 | 
			
		||||
            PanDescriptor::try_from(&buf[124..146])?,
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        let mut uwb_energy_detect_list = [0; MAX_ED_SCAN_RESULTS_SUPPORTED];
 | 
			
		||||
        uwb_energy_detect_list.copy_from_slice(&buf[147..163]);
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            status: MacStatus::try_from(buf[0])?,
 | 
			
		||||
            scan_type: ScanType::try_from(buf[1])?,
 | 
			
		||||
            channel_page: buf[2],
 | 
			
		||||
            unscanned_channels: [buf[3], buf[4], buf[5], buf[6]],
 | 
			
		||||
            result_list_size: buf[7],
 | 
			
		||||
            energy_detect_list,
 | 
			
		||||
            pan_descriptor_list,
 | 
			
		||||
            detected_category: buf[146],
 | 
			
		||||
            uwb_energy_detect_list,
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ParseableMacEvent for ScanConfirm {}
 | 
			
		||||
 | 
			
		||||
/// MLME SET Confirm which reports the result of an attempt to write a value to a PIB attribute
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct SetConfirm {
 | 
			
		||||
    /// The result of the set operation
 | 
			
		||||
    pub status: MacStatus,
 | 
			
		||||
    /// The name of the PIB attribute that was written
 | 
			
		||||
    pub pin_attribute: PibId,
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    a_stuffing: [u8; 2],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for SetConfirm {
 | 
			
		||||
    const SIZE: usize = 4;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            status: MacStatus::try_from(buf[0])?,
 | 
			
		||||
            pin_attribute: PibId::try_from(buf[1])?,
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ParseableMacEvent for SetConfirm {}
 | 
			
		||||
 | 
			
		||||
/// MLME START Confirm which is used to report the results of the attempt to
 | 
			
		||||
/// start using a new superframe configuration
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct StartConfirm {
 | 
			
		||||
    /// Result of the attempt to start using an updated superframe configuration
 | 
			
		||||
    pub status: MacStatus,
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    a_stuffing: [u8; 3],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for StartConfirm {
 | 
			
		||||
    const SIZE: usize = 4;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            status: MacStatus::try_from(buf[0])?,
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ParseableMacEvent for StartConfirm {}
 | 
			
		||||
 | 
			
		||||
/// MLME POLL Confirm which is used to report the result of a request to poll the coordinator for data
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct PollConfirm {
 | 
			
		||||
    /// The status of the data request
 | 
			
		||||
    pub status: MacStatus,
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    a_stuffing: [u8; 3],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for PollConfirm {
 | 
			
		||||
    const SIZE: usize = 4;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            status: MacStatus::try_from(buf[0])?,
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ParseableMacEvent for PollConfirm {}
 | 
			
		||||
 | 
			
		||||
/// MLME DPS Confirm which  reports the results of the attempt to enable or disable the DPS
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct DpsConfirm {
 | 
			
		||||
    /// The status of the DPS request
 | 
			
		||||
    pub status: MacStatus,
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    a_stuffing: [u8; 3],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for DpsConfirm {
 | 
			
		||||
    const SIZE: usize = 4;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            status: MacStatus::try_from(buf[0])?,
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ParseableMacEvent for DpsConfirm {}
 | 
			
		||||
 | 
			
		||||
/// MLME SOUNDING Confirm which  reports the result of a request to the PHY to provide
 | 
			
		||||
/// channel sounding information
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct SoundingConfirm {
 | 
			
		||||
    /// Results of the sounding measurement
 | 
			
		||||
    sounding_list: [u8; MAX_SOUNDING_LIST_SUPPORTED],
 | 
			
		||||
 | 
			
		||||
    status: u8,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for SoundingConfirm {
 | 
			
		||||
    const SIZE: usize = 1;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        let mut sounding_list = [0u8; MAX_SOUNDING_LIST_SUPPORTED];
 | 
			
		||||
        sounding_list[..buf.len()].copy_from_slice(buf);
 | 
			
		||||
 | 
			
		||||
        Ok(Self { sounding_list })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ParseableMacEvent for SoundingConfirm {}
 | 
			
		||||
 | 
			
		||||
/// MLME CALIBRATE Confirm which reports the result of a request to the PHY
 | 
			
		||||
/// to provide internal propagation path information
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct CalibrateConfirm {
 | 
			
		||||
    /// The status of the attempt to return sounding data
 | 
			
		||||
    pub status: MacStatus,
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    a_stuffing: [u8; 3],
 | 
			
		||||
    /// A count of the propagation time from the ranging counter
 | 
			
		||||
    /// to the transmit antenna
 | 
			
		||||
    pub cal_tx_rmaker_offset: u32,
 | 
			
		||||
@@ -348,23 +209,11 @@ pub struct CalibrateConfirm {
 | 
			
		||||
    pub cal_rx_rmaker_offset: u32,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for CalibrateConfirm {
 | 
			
		||||
    const SIZE: usize = 12;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            status: MacStatus::try_from(buf[0])?,
 | 
			
		||||
            // 3 byte stuffing
 | 
			
		||||
            cal_tx_rmaker_offset: to_u32(&buf[4..8]),
 | 
			
		||||
            cal_rx_rmaker_offset: to_u32(&buf[8..12]),
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ParseableMacEvent for CalibrateConfirm {}
 | 
			
		||||
 | 
			
		||||
/// MCPS DATA Confirm which will be used for reporting the results of
 | 
			
		||||
/// MAC data related requests from the application
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct DataConfirm {
 | 
			
		||||
    /// The handle associated with the MSDU being confirmed
 | 
			
		||||
@@ -387,47 +236,23 @@ pub struct DataConfirm {
 | 
			
		||||
    pub ranging_offset: u32,
 | 
			
		||||
    /// The FoM characterizing the ranging measurement
 | 
			
		||||
    pub ranging_fom: u8,
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    a_stuffing: [u8; 3],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for DataConfirm {
 | 
			
		||||
    const SIZE: usize = 28;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            msdu_handle: buf[0],
 | 
			
		||||
            time_stamp: [buf[1], buf[2], buf[3], buf[4]],
 | 
			
		||||
            ranging_received: buf[5],
 | 
			
		||||
            status: MacStatus::try_from(buf[6])?,
 | 
			
		||||
            ranging_counter_start: to_u32(&buf[7..11]),
 | 
			
		||||
            ranging_counter_stop: to_u32(&buf[11..15]),
 | 
			
		||||
            ranging_tracking_interval: to_u32(&buf[15..19]),
 | 
			
		||||
            ranging_offset: to_u32(&buf[19..23]),
 | 
			
		||||
            ranging_fom: buf[24],
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ParseableMacEvent for DataConfirm {}
 | 
			
		||||
 | 
			
		||||
/// MCPS PURGE Confirm which will be used by the  MAC to notify the application of
 | 
			
		||||
/// the status of its request to purge an MSDU from the transaction queue
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
pub struct PurgeConfirm {
 | 
			
		||||
    /// Handle associated with the MSDU requested to be purged from the transaction queue
 | 
			
		||||
    pub msdu_handle: u8,
 | 
			
		||||
    /// The status of the request
 | 
			
		||||
    pub status: MacStatus,
 | 
			
		||||
    /// byte stuffing to keep 32 bit alignment
 | 
			
		||||
    a_stuffing: [u8; 2],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ParseableMacEvent for PurgeConfirm {
 | 
			
		||||
    const SIZE: usize = 4;
 | 
			
		||||
 | 
			
		||||
    fn try_parse(buf: &[u8]) -> Result<Self, ()> {
 | 
			
		||||
        Self::validate(buf)?;
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            msdu_handle: buf[0],
 | 
			
		||||
            status: MacStatus::try_from(buf[1])?,
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl ParseableMacEvent for PurgeConfirm {}
 | 
			
		||||
 
 | 
			
		||||
@@ -37,9 +37,11 @@ numeric_enum! {
 | 
			
		||||
numeric_enum! {
 | 
			
		||||
    #[repr(u8)]
 | 
			
		||||
    /// this enum contains all the MAC PIB Ids
 | 
			
		||||
    #[derive(Default)]
 | 
			
		||||
    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 | 
			
		||||
    pub enum PibId {
 | 
			
		||||
        // PHY
 | 
			
		||||
        #[default]
 | 
			
		||||
        CurrentChannel = 0x00,
 | 
			
		||||
        ChannelsSupported = 0x01,
 | 
			
		||||
        TransmitPower = 0x02,
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@ use crate::cmd::CmdPacket;
 | 
			
		||||
use crate::consts::TlPacketType;
 | 
			
		||||
use crate::evt::{EvtBox, EvtPacket};
 | 
			
		||||
use crate::mac::commands::MacCommand;
 | 
			
		||||
use crate::mac::event::MacEvent;
 | 
			
		||||
use crate::mac::event::Event;
 | 
			
		||||
use crate::mac::typedefs::MacError;
 | 
			
		||||
use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER};
 | 
			
		||||
use crate::{channels, evt};
 | 
			
		||||
@@ -85,12 +85,7 @@ impl Mac {
 | 
			
		||||
    where
 | 
			
		||||
        T: MacCommand,
 | 
			
		||||
    {
 | 
			
		||||
        let mut payload = [0u8; MAX_PACKET_SIZE];
 | 
			
		||||
        cmd.copy_into_slice(&mut payload);
 | 
			
		||||
 | 
			
		||||
        let response = self
 | 
			
		||||
            .tl_write_and_get_response(T::OPCODE as u16, &payload[..T::SIZE])
 | 
			
		||||
            .await;
 | 
			
		||||
        let response = self.tl_write_and_get_response(T::OPCODE as u16, cmd.payload()).await;
 | 
			
		||||
 | 
			
		||||
        if response == 0x00 {
 | 
			
		||||
            Ok(())
 | 
			
		||||
@@ -99,16 +94,11 @@ impl Mac {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn read(&self) -> Result<MacEvent, ()> {
 | 
			
		||||
        let evt_box = self.tl_read().await;
 | 
			
		||||
        let payload = evt_box.payload();
 | 
			
		||||
 | 
			
		||||
        MacEvent::try_from(payload)
 | 
			
		||||
    pub async fn read(&self) -> Event {
 | 
			
		||||
        Event::new(self.tl_read().await)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const MAX_PACKET_SIZE: usize = 255;
 | 
			
		||||
 | 
			
		||||
impl evt::MemoryManager for Mac {
 | 
			
		||||
    /// SAFETY: passing a pointer to something other than a managed event packet is UB
 | 
			
		||||
    unsafe fn drop_event_packet(_: *mut EvtPacket) {
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,7 @@ display-interface = "0.4.1"
 | 
			
		||||
byte-slice-cast = { version = "1.2.0", default-features = false }
 | 
			
		||||
smart-leds = "0.3.0"
 | 
			
		||||
heapless = "0.7.15"
 | 
			
		||||
usbd-hid = "0.6.1"
 | 
			
		||||
 | 
			
		||||
embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" }
 | 
			
		||||
embedded-hal-async = "0.2.0-alpha.2"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										188
									
								
								examples/rp/src/bin/usb_hid_keyboard.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								examples/rp/src/bin/usb_hid_keyboard.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,188 @@
 | 
			
		||||
#![no_std]
 | 
			
		||||
#![no_main]
 | 
			
		||||
#![feature(type_alias_impl_trait)]
 | 
			
		||||
 | 
			
		||||
use core::sync::atomic::{AtomicBool, Ordering};
 | 
			
		||||
 | 
			
		||||
use defmt::*;
 | 
			
		||||
use embassy_executor::Spawner;
 | 
			
		||||
use embassy_futures::join::join;
 | 
			
		||||
use embassy_rp::bind_interrupts;
 | 
			
		||||
use embassy_rp::gpio::{Input, Pull};
 | 
			
		||||
use embassy_rp::peripherals::USB;
 | 
			
		||||
use embassy_rp::usb::{Driver, InterruptHandler};
 | 
			
		||||
use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State};
 | 
			
		||||
use embassy_usb::control::OutResponse;
 | 
			
		||||
use embassy_usb::{Builder, Config, Handler};
 | 
			
		||||
use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
 | 
			
		||||
use {defmt_rtt as _, panic_probe as _};
 | 
			
		||||
 | 
			
		||||
bind_interrupts!(struct Irqs {
 | 
			
		||||
    USBCTRL_IRQ => InterruptHandler<USB>;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
#[embassy_executor::main]
 | 
			
		||||
async fn main(_spawner: Spawner) {
 | 
			
		||||
    let p = embassy_rp::init(Default::default());
 | 
			
		||||
    // Create the driver, from the HAL.
 | 
			
		||||
    let driver = Driver::new(p.USB, Irqs);
 | 
			
		||||
 | 
			
		||||
    // Create embassy-usb Config
 | 
			
		||||
    let mut config = Config::new(0xc0de, 0xcafe);
 | 
			
		||||
    config.manufacturer = Some("Embassy");
 | 
			
		||||
    config.product = Some("HID keyboard example");
 | 
			
		||||
    config.serial_number = Some("12345678");
 | 
			
		||||
    config.max_power = 100;
 | 
			
		||||
    config.max_packet_size_0 = 64;
 | 
			
		||||
 | 
			
		||||
    // Create embassy-usb DeviceBuilder using the driver and config.
 | 
			
		||||
    // It needs some buffers for building the descriptors.
 | 
			
		||||
    let mut device_descriptor = [0; 256];
 | 
			
		||||
    let mut config_descriptor = [0; 256];
 | 
			
		||||
    let mut bos_descriptor = [0; 256];
 | 
			
		||||
    // You can also add a Microsoft OS descriptor.
 | 
			
		||||
    // let mut msos_descriptor = [0; 256];
 | 
			
		||||
    let mut control_buf = [0; 64];
 | 
			
		||||
    let request_handler = MyRequestHandler {};
 | 
			
		||||
    let mut device_handler = MyDeviceHandler::new();
 | 
			
		||||
 | 
			
		||||
    let mut state = State::new();
 | 
			
		||||
 | 
			
		||||
    let mut builder = Builder::new(
 | 
			
		||||
        driver,
 | 
			
		||||
        config,
 | 
			
		||||
        &mut device_descriptor,
 | 
			
		||||
        &mut config_descriptor,
 | 
			
		||||
        &mut bos_descriptor,
 | 
			
		||||
        // &mut msos_descriptor,
 | 
			
		||||
        &mut control_buf,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    builder.handler(&mut device_handler);
 | 
			
		||||
 | 
			
		||||
    // Create classes on the builder.
 | 
			
		||||
    let config = embassy_usb::class::hid::Config {
 | 
			
		||||
        report_descriptor: KeyboardReport::desc(),
 | 
			
		||||
        request_handler: Some(&request_handler),
 | 
			
		||||
        poll_ms: 60,
 | 
			
		||||
        max_packet_size: 64,
 | 
			
		||||
    };
 | 
			
		||||
    let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config);
 | 
			
		||||
 | 
			
		||||
    // Build the builder.
 | 
			
		||||
    let mut usb = builder.build();
 | 
			
		||||
 | 
			
		||||
    // Run the USB device.
 | 
			
		||||
    let usb_fut = usb.run();
 | 
			
		||||
 | 
			
		||||
    // Set up the signal pin that will be used to trigger the keyboard.
 | 
			
		||||
    let mut signal_pin = Input::new(p.PIN_16, Pull::None);
 | 
			
		||||
 | 
			
		||||
    let (reader, mut writer) = hid.split();
 | 
			
		||||
 | 
			
		||||
    // Do stuff with the class!
 | 
			
		||||
    let in_fut = async {
 | 
			
		||||
        loop {
 | 
			
		||||
            info!("Waiting for HIGH on pin 16");
 | 
			
		||||
            signal_pin.wait_for_high().await;
 | 
			
		||||
            info!("HIGH DETECTED");
 | 
			
		||||
            // Create a report with the A key pressed. (no shift modifier)
 | 
			
		||||
            let report = KeyboardReport {
 | 
			
		||||
                keycodes: [4, 0, 0, 0, 0, 0],
 | 
			
		||||
                leds: 0,
 | 
			
		||||
                modifier: 0,
 | 
			
		||||
                reserved: 0,
 | 
			
		||||
            };
 | 
			
		||||
            // Send the report.
 | 
			
		||||
            match writer.write_serialize(&report).await {
 | 
			
		||||
                Ok(()) => {}
 | 
			
		||||
                Err(e) => warn!("Failed to send report: {:?}", e),
 | 
			
		||||
            };
 | 
			
		||||
            signal_pin.wait_for_low().await;
 | 
			
		||||
            info!("LOW DETECTED");
 | 
			
		||||
            let report = KeyboardReport {
 | 
			
		||||
                keycodes: [0, 0, 0, 0, 0, 0],
 | 
			
		||||
                leds: 0,
 | 
			
		||||
                modifier: 0,
 | 
			
		||||
                reserved: 0,
 | 
			
		||||
            };
 | 
			
		||||
            match writer.write_serialize(&report).await {
 | 
			
		||||
                Ok(()) => {}
 | 
			
		||||
                Err(e) => warn!("Failed to send report: {:?}", e),
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let out_fut = async {
 | 
			
		||||
        reader.run(false, &request_handler).await;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Run everything concurrently.
 | 
			
		||||
    // If we had made everything `'static` above instead, we could do this using separate tasks instead.
 | 
			
		||||
    join(usb_fut, join(in_fut, out_fut)).await;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct MyRequestHandler {}
 | 
			
		||||
 | 
			
		||||
impl RequestHandler for MyRequestHandler {
 | 
			
		||||
    fn get_report(&self, id: ReportId, _buf: &mut [u8]) -> Option<usize> {
 | 
			
		||||
        info!("Get report for {:?}", id);
 | 
			
		||||
        None
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn set_report(&self, id: ReportId, data: &[u8]) -> OutResponse {
 | 
			
		||||
        info!("Set report for {:?}: {=[u8]}", id, data);
 | 
			
		||||
        OutResponse::Accepted
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn set_idle_ms(&self, id: Option<ReportId>, dur: u32) {
 | 
			
		||||
        info!("Set idle rate for {:?} to {:?}", id, dur);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn get_idle_ms(&self, id: Option<ReportId>) -> Option<u32> {
 | 
			
		||||
        info!("Get idle rate for {:?}", id);
 | 
			
		||||
        None
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct MyDeviceHandler {
 | 
			
		||||
    configured: AtomicBool,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl MyDeviceHandler {
 | 
			
		||||
    fn new() -> Self {
 | 
			
		||||
        MyDeviceHandler {
 | 
			
		||||
            configured: AtomicBool::new(false),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Handler for MyDeviceHandler {
 | 
			
		||||
    fn enabled(&mut self, enabled: bool) {
 | 
			
		||||
        self.configured.store(false, Ordering::Relaxed);
 | 
			
		||||
        if enabled {
 | 
			
		||||
            info!("Device enabled");
 | 
			
		||||
        } else {
 | 
			
		||||
            info!("Device disabled");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn reset(&mut self) {
 | 
			
		||||
        self.configured.store(false, Ordering::Relaxed);
 | 
			
		||||
        info!("Bus reset, the Vbus current limit is 100mA");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn addressed(&mut self, addr: u8) {
 | 
			
		||||
        self.configured.store(false, Ordering::Relaxed);
 | 
			
		||||
        info!("USB address set to: {}", addr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn configured(&mut self, configured: bool) {
 | 
			
		||||
        self.configured.store(configured, Ordering::Relaxed);
 | 
			
		||||
        if configured {
 | 
			
		||||
            info!("Device configured, it may now draw up to the configured current limit from Vbus.")
 | 
			
		||||
        } else {
 | 
			
		||||
            info!("Device is no longer configured, the Vbus current limit is 100mA.");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -67,11 +67,16 @@ async fn main(spawner: Spawner) {
 | 
			
		||||
 | 
			
		||||
    info!("resetting");
 | 
			
		||||
    mbox.mac_subsystem
 | 
			
		||||
        .send_command(&ResetRequest { set_default_pib: true })
 | 
			
		||||
        .send_command(&ResetRequest {
 | 
			
		||||
            set_default_pib: true,
 | 
			
		||||
            ..Default::default()
 | 
			
		||||
        })
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
    let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
    defmt::info!("{:#x}", evt);
 | 
			
		||||
    {
 | 
			
		||||
        let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
        defmt::info!("{:#x}", evt.mac_event());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    info!("setting extended address");
 | 
			
		||||
    let extended_address: u64 = 0xACDE480000000001;
 | 
			
		||||
@@ -82,8 +87,10 @@ async fn main(spawner: Spawner) {
 | 
			
		||||
        })
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
    let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
    defmt::info!("{:#x}", evt);
 | 
			
		||||
    {
 | 
			
		||||
        let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
        defmt::info!("{:#x}", evt.mac_event());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    info!("setting short address");
 | 
			
		||||
    let short_address: u16 = 0x1122;
 | 
			
		||||
@@ -94,8 +101,10 @@ async fn main(spawner: Spawner) {
 | 
			
		||||
        })
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
    let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
    defmt::info!("{:#x}", evt);
 | 
			
		||||
    {
 | 
			
		||||
        let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
        defmt::info!("{:#x}", evt.mac_event());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    info!("setting association permit");
 | 
			
		||||
    let association_permit: bool = true;
 | 
			
		||||
@@ -106,8 +115,10 @@ async fn main(spawner: Spawner) {
 | 
			
		||||
        })
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
    let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
    defmt::info!("{:#x}", evt);
 | 
			
		||||
    {
 | 
			
		||||
        let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
        defmt::info!("{:#x}", evt.mac_event());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    info!("setting TX power");
 | 
			
		||||
    let transmit_power: i8 = 2;
 | 
			
		||||
@@ -118,8 +129,10 @@ async fn main(spawner: Spawner) {
 | 
			
		||||
        })
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
    let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
    defmt::info!("{:#x}", evt);
 | 
			
		||||
    {
 | 
			
		||||
        let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
        defmt::info!("{:#x}", evt.mac_event());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    info!("starting FFD device");
 | 
			
		||||
    mbox.mac_subsystem
 | 
			
		||||
@@ -134,8 +147,10 @@ async fn main(spawner: Spawner) {
 | 
			
		||||
        })
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
    let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
    defmt::info!("{:#x}", evt);
 | 
			
		||||
    {
 | 
			
		||||
        let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
        defmt::info!("{:#x}", evt.mac_event());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    info!("setting RX on when idle");
 | 
			
		||||
    let rx_on_while_idle: bool = true;
 | 
			
		||||
@@ -146,14 +161,17 @@ async fn main(spawner: Spawner) {
 | 
			
		||||
        })
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
    let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
    defmt::info!("{:#x}", evt);
 | 
			
		||||
    {
 | 
			
		||||
        let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
        defmt::info!("{:#x}", evt.mac_event());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    loop {
 | 
			
		||||
        let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
        defmt::info!("{:#x}", evt);
 | 
			
		||||
        if let Ok(evt) = evt.mac_event() {
 | 
			
		||||
            defmt::info!("parsed mac event");
 | 
			
		||||
            defmt::info!("{:#x}", evt);
 | 
			
		||||
 | 
			
		||||
        if let Ok(evt) = evt {
 | 
			
		||||
            match evt {
 | 
			
		||||
                MacEvent::MlmeAssociateInd(association) => mbox
 | 
			
		||||
                    .mac_subsystem
 | 
			
		||||
@@ -167,17 +185,22 @@ async fn main(spawner: Spawner) {
 | 
			
		||||
                    .await
 | 
			
		||||
                    .unwrap(),
 | 
			
		||||
                MacEvent::McpsDataInd(data_ind) => {
 | 
			
		||||
                    let data_addr = data_ind.msdu_ptr;
 | 
			
		||||
                    let mut data = [0u8; 256];
 | 
			
		||||
                    unsafe { data_addr.copy_to(&mut data as *mut _, data_ind.msdu_length as usize) }
 | 
			
		||||
                    info!("{}", data[..data_ind.msdu_length as usize]);
 | 
			
		||||
                    let payload = data_ind.payload();
 | 
			
		||||
                    let ref_payload = b"Hello from embassy!";
 | 
			
		||||
                    info!("{}", payload);
 | 
			
		||||
 | 
			
		||||
                    if &data[..data_ind.msdu_length as usize] == b"Hello from embassy!" {
 | 
			
		||||
                    if payload == ref_payload {
 | 
			
		||||
                        info!("success");
 | 
			
		||||
                    } else {
 | 
			
		||||
                        info!("ref payload: {}", ref_payload);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                _ => {}
 | 
			
		||||
                _ => {
 | 
			
		||||
                    defmt::info!("other mac event");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            defmt::info!("failed to parse mac event");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -69,11 +69,16 @@ async fn main(spawner: Spawner) {
 | 
			
		||||
 | 
			
		||||
    info!("resetting");
 | 
			
		||||
    mbox.mac_subsystem
 | 
			
		||||
        .send_command(&ResetRequest { set_default_pib: true })
 | 
			
		||||
        .send_command(&ResetRequest {
 | 
			
		||||
            set_default_pib: true,
 | 
			
		||||
            ..Default::default()
 | 
			
		||||
        })
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
    let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
    info!("{:#x}", evt);
 | 
			
		||||
    {
 | 
			
		||||
        let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
        defmt::info!("{:#x}", evt.mac_event());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    info!("setting extended address");
 | 
			
		||||
    let extended_address: u64 = 0xACDE480000000002;
 | 
			
		||||
@@ -84,24 +89,30 @@ async fn main(spawner: Spawner) {
 | 
			
		||||
        })
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
    let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
    info!("{:#x}", evt);
 | 
			
		||||
    {
 | 
			
		||||
        let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
        defmt::info!("{:#x}", evt.mac_event());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    info!("getting extended address");
 | 
			
		||||
    mbox.mac_subsystem
 | 
			
		||||
        .send_command(&GetRequest {
 | 
			
		||||
            pib_attribute: PibId::ExtendedAddress,
 | 
			
		||||
            ..Default::default()
 | 
			
		||||
        })
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
    let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
    info!("{:#x}", evt);
 | 
			
		||||
 | 
			
		||||
    if let Ok(MacEvent::MlmeGetCnf(evt)) = evt {
 | 
			
		||||
        if evt.pib_attribute_value_len == 8 {
 | 
			
		||||
            let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) };
 | 
			
		||||
    {
 | 
			
		||||
        let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
        info!("{:#x}", evt.mac_event());
 | 
			
		||||
 | 
			
		||||
            info!("value {:#x}", value)
 | 
			
		||||
        if let Ok(MacEvent::MlmeGetCnf(evt)) = evt.mac_event() {
 | 
			
		||||
            if evt.pib_attribute_value_len == 8 {
 | 
			
		||||
                let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) };
 | 
			
		||||
 | 
			
		||||
                info!("value {:#x}", value)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -120,13 +131,15 @@ async fn main(spawner: Spawner) {
 | 
			
		||||
    };
 | 
			
		||||
    info!("{}", a);
 | 
			
		||||
    mbox.mac_subsystem.send_command(&a).await.unwrap();
 | 
			
		||||
    let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
    info!("{:#x}", evt);
 | 
			
		||||
    let short_addr = {
 | 
			
		||||
        let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
        info!("{:#x}", evt.mac_event());
 | 
			
		||||
 | 
			
		||||
    let short_addr = if let Ok(MacEvent::MlmeAssociateCnf(conf)) = evt {
 | 
			
		||||
        conf.assoc_short_address
 | 
			
		||||
    } else {
 | 
			
		||||
        defmt::panic!()
 | 
			
		||||
        if let Ok(MacEvent::MlmeAssociateCnf(conf)) = evt.mac_event() {
 | 
			
		||||
            conf.assoc_short_address
 | 
			
		||||
        } else {
 | 
			
		||||
            defmt::panic!()
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    info!("setting short address");
 | 
			
		||||
@@ -137,34 +150,37 @@ async fn main(spawner: Spawner) {
 | 
			
		||||
        })
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
    let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
    info!("{:#x}", evt);
 | 
			
		||||
    {
 | 
			
		||||
        let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
        info!("{:#x}", evt.mac_event());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    info!("sending data");
 | 
			
		||||
    let mut data_buffer = [0u8; 256];
 | 
			
		||||
    let data = b"Hello from embassy!";
 | 
			
		||||
    data_buffer[..data.len()].copy_from_slice(data);
 | 
			
		||||
    mbox.mac_subsystem
 | 
			
		||||
        .send_command(&DataRequest {
 | 
			
		||||
            src_addr_mode: AddressMode::Short,
 | 
			
		||||
            dst_addr_mode: AddressMode::Short,
 | 
			
		||||
            dst_pan_id: PanId([0x1A, 0xAA]),
 | 
			
		||||
            dst_address: MacAddress::BROADCAST,
 | 
			
		||||
            msdu_handle: 0x02,
 | 
			
		||||
            ack_tx: 0x00,
 | 
			
		||||
            gts_tx: false,
 | 
			
		||||
            msdu_ptr: &data_buffer as *const _ as *const u8,
 | 
			
		||||
            msdu_length: data.len() as u8,
 | 
			
		||||
            security_level: SecurityLevel::Unsecure,
 | 
			
		||||
            ..Default::default()
 | 
			
		||||
        })
 | 
			
		||||
        .send_command(
 | 
			
		||||
            DataRequest {
 | 
			
		||||
                src_addr_mode: AddressMode::Short,
 | 
			
		||||
                dst_addr_mode: AddressMode::Short,
 | 
			
		||||
                dst_pan_id: PanId([0x1A, 0xAA]),
 | 
			
		||||
                dst_address: MacAddress::BROADCAST,
 | 
			
		||||
                msdu_handle: 0x02,
 | 
			
		||||
                ack_tx: 0x00,
 | 
			
		||||
                gts_tx: false,
 | 
			
		||||
                security_level: SecurityLevel::Unsecure,
 | 
			
		||||
                ..Default::default()
 | 
			
		||||
            }
 | 
			
		||||
            .set_buffer(data),
 | 
			
		||||
        )
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
    let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
    info!("{:#x}", evt);
 | 
			
		||||
    {
 | 
			
		||||
        let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
        info!("{:#x}", evt.mac_event());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    loop {
 | 
			
		||||
        let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
        info!("{:#x}", evt);
 | 
			
		||||
        info!("{:#x}", evt.mac_event());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -49,11 +49,16 @@ async fn main(spawner: Spawner) {
 | 
			
		||||
 | 
			
		||||
    info!("resetting");
 | 
			
		||||
    mbox.mac_subsystem
 | 
			
		||||
        .send_command(&ResetRequest { set_default_pib: true })
 | 
			
		||||
        .send_command(&ResetRequest {
 | 
			
		||||
            set_default_pib: true,
 | 
			
		||||
            ..Default::default()
 | 
			
		||||
        })
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
    let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
    info!("{:#x}", evt);
 | 
			
		||||
    {
 | 
			
		||||
        let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
        info!("{:#x}", evt.mac_event());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    info!("setting extended address");
 | 
			
		||||
    let extended_address: u64 = 0xACDE480000000002;
 | 
			
		||||
@@ -64,24 +69,29 @@ async fn main(spawner: Spawner) {
 | 
			
		||||
        })
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
    let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
    info!("{:#x}", evt);
 | 
			
		||||
    {
 | 
			
		||||
        let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
        info!("{:#x}", evt.mac_event());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    info!("getting extended address");
 | 
			
		||||
    mbox.mac_subsystem
 | 
			
		||||
        .send_command(&GetRequest {
 | 
			
		||||
            pib_attribute: PibId::ExtendedAddress,
 | 
			
		||||
            ..Default::default()
 | 
			
		||||
        })
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
    let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
    info!("{:#x}", evt);
 | 
			
		||||
    {
 | 
			
		||||
        let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
        info!("{:#x}", evt.mac_event());
 | 
			
		||||
 | 
			
		||||
    if let Ok(MacEvent::MlmeGetCnf(evt)) = evt {
 | 
			
		||||
        if evt.pib_attribute_value_len == 8 {
 | 
			
		||||
            let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) };
 | 
			
		||||
        if let Ok(MacEvent::MlmeGetCnf(evt)) = evt.mac_event() {
 | 
			
		||||
            if evt.pib_attribute_value_len == 8 {
 | 
			
		||||
                let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) };
 | 
			
		||||
 | 
			
		||||
            info!("value {:#x}", value)
 | 
			
		||||
                info!("value {:#x}", value)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -100,8 +110,10 @@ async fn main(spawner: Spawner) {
 | 
			
		||||
    };
 | 
			
		||||
    info!("{}", a);
 | 
			
		||||
    mbox.mac_subsystem.send_command(&a).await.unwrap();
 | 
			
		||||
    let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
    info!("{:#x}", evt);
 | 
			
		||||
    {
 | 
			
		||||
        let evt = mbox.mac_subsystem.read().await;
 | 
			
		||||
        info!("{:#x}", evt.mac_event());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    info!("Test OK");
 | 
			
		||||
    cortex_m::asm::bkpt();
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user