Merge branch 'master' into mac
This commit is contained in:
commit
1d2c47273d
@ -1,15 +1,16 @@
|
|||||||
|
use core::{mem, slice};
|
||||||
|
|
||||||
use super::opcodes::OpcodeM4ToM0;
|
use super::opcodes::OpcodeM4ToM0;
|
||||||
use super::typedefs::{
|
use super::typedefs::{
|
||||||
AddressMode, Capabilities, DisassociationReason, GtsCharacteristics, KeyIdMode, MacAddress, MacChannel, MacStatus,
|
AddressMode, Capabilities, DisassociationReason, GtsCharacteristics, KeyIdMode, MacAddress, MacChannel, MacStatus,
|
||||||
PanId, PibId, ScanType, SecurityLevel,
|
PanId, PibId, ScanType, SecurityLevel,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait MacCommand {
|
pub trait MacCommand: Sized {
|
||||||
const OPCODE: OpcodeM4ToM0;
|
const OPCODE: OpcodeM4ToM0;
|
||||||
const SIZE: usize;
|
|
||||||
|
|
||||||
fn copy_into_slice(&self, buf: &mut [u8]) {
|
fn payload<'a>(&'a self) -> &'a [u8] {
|
||||||
unsafe { core::ptr::copy(self as *const _ as *const u8, buf as *mut _ as *mut u8, Self::SIZE) };
|
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 {
|
impl MacCommand for AssociateRequest {
|
||||||
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeAssociateReq;
|
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeAssociateReq;
|
||||||
const SIZE: usize = 25;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// MLME DISASSOCIATE Request sed to request a disassociation
|
/// MLME DISASSOCIATE Request sed to request a disassociation
|
||||||
@ -70,20 +70,22 @@ pub struct DisassociateRequest {
|
|||||||
|
|
||||||
impl MacCommand for DisassociateRequest {
|
impl MacCommand for DisassociateRequest {
|
||||||
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeDisassociateReq;
|
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeDisassociateReq;
|
||||||
const SIZE: usize = 24;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// MLME GET Request used to request a PIB value
|
/// MLME GET Request used to request a PIB value
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Default)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct GetRequest {
|
pub struct GetRequest {
|
||||||
/// the name of the PIB attribute to read
|
/// the name of the PIB attribute to read
|
||||||
pub pib_attribute: PibId,
|
pub pib_attribute: PibId,
|
||||||
|
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
|
pub a_stuffing: [u8; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MacCommand for GetRequest {
|
impl MacCommand for GetRequest {
|
||||||
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeGetReq;
|
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeGetReq;
|
||||||
const SIZE: usize = 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// MLME GTS Request used to request and maintain GTSs
|
/// MLME GTS Request used to request and maintain GTSs
|
||||||
@ -104,19 +106,20 @@ pub struct GtsRequest {
|
|||||||
|
|
||||||
impl MacCommand for GtsRequest {
|
impl MacCommand for GtsRequest {
|
||||||
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeGetReq;
|
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeGetReq;
|
||||||
const SIZE: usize = 12;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Default)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct ResetRequest {
|
pub struct ResetRequest {
|
||||||
/// MAC PIB attributes are set to their default values or not during reset
|
/// MAC PIB attributes are set to their default values or not during reset
|
||||||
pub set_default_pib: bool,
|
pub set_default_pib: bool,
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
|
pub a_stuffing: [u8; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MacCommand for ResetRequest {
|
impl MacCommand for ResetRequest {
|
||||||
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeResetReq;
|
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeResetReq;
|
||||||
const SIZE: usize = 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// MLME RX ENABLE Request used to request that the receiver is either enabled
|
/// 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
|
/// configure the transceiver to RX with ranging for a value of
|
||||||
/// RANGING_ON or to not enable ranging for RANGING_OFF
|
/// RANGING_ON or to not enable ranging for RANGING_OFF
|
||||||
pub ranging_rx_control: u8,
|
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
|
/// number of symbols measured before the receiver is to be enabled or disabled
|
||||||
pub rx_on_time: [u8; 4],
|
pub rx_on_time: [u8; 4],
|
||||||
/// number of symbols for which the receiver is to be enabled
|
/// number of symbols for which the receiver is to be enabled
|
||||||
@ -137,19 +142,6 @@ pub struct RxEnableRequest {
|
|||||||
|
|
||||||
impl MacCommand for RxEnableRequest {
|
impl MacCommand for RxEnableRequest {
|
||||||
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeRxEnableReq;
|
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
|
/// 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,
|
pub key_id_mode: KeyIdMode,
|
||||||
/// index of the key to be used
|
/// index of the key to be used
|
||||||
pub key_index: u8,
|
pub key_index: u8,
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
|
pub a_stuffing: [u8; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MacCommand for ScanRequest {
|
impl MacCommand for ScanRequest {
|
||||||
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeScanReq;
|
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
|
/// 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 {
|
impl MacCommand for SetRequest {
|
||||||
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSetReq;
|
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
|
/// MLME START Request used by the FFDs to intiate a new PAN or to begin using a new superframe
|
||||||
/// configuration
|
/// configuration
|
||||||
#[derive(Default)]
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Default)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct StartRequest {
|
pub struct StartRequest {
|
||||||
/// PAN indentifier to used by the device
|
/// PAN indentifier to used by the device
|
||||||
@ -236,7 +228,6 @@ pub struct StartRequest {
|
|||||||
|
|
||||||
impl MacCommand for StartRequest {
|
impl MacCommand for StartRequest {
|
||||||
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeStartReq;
|
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeStartReq;
|
||||||
const SIZE: usize = 35;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// MLME SYNC Request used to synchronize with the coordinator by acquiring and, if
|
/// 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
|
/// `false` if the MLME is to synchronize with only the next beacon
|
||||||
pub track_beacon: bool,
|
pub track_beacon: bool,
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
|
pub a_stuffing: [u8; 1],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MacCommand for SyncRequest {
|
impl MacCommand for SyncRequest {
|
||||||
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSyncReq;
|
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSyncReq;
|
||||||
const SIZE: usize = 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// MLME POLL Request propmts the device to request data from the coordinator
|
/// MLME POLL Request propmts the device to request data from the coordinator
|
||||||
@ -278,11 +270,12 @@ pub struct PollRequest {
|
|||||||
pub key_source: [u8; 8],
|
pub key_source: [u8; 8],
|
||||||
/// PAN identifier of the coordinator
|
/// PAN identifier of the coordinator
|
||||||
pub coord_pan_id: PanId,
|
pub coord_pan_id: PanId,
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
|
pub a_stuffing: [u8; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MacCommand for PollRequest {
|
impl MacCommand for PollRequest {
|
||||||
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmePollReq;
|
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmePollReq;
|
||||||
const SIZE: usize = 24;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// MLME DPS Request allows the next higher layer to request that the PHY utilize a
|
/// 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
|
/// the number of symbols for which the transmitter and receiver will utilize the
|
||||||
/// respective DPS indices
|
/// respective DPS indices
|
||||||
dps_index_duration: u8,
|
dps_index_duration: u8,
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
|
pub a_stuffing: [u8; 1],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MacCommand for DpsRequest {
|
impl MacCommand for DpsRequest {
|
||||||
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeDpsReq;
|
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeDpsReq;
|
||||||
const SIZE: usize = 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// MLME SOUNDING request primitive which is used by the next higher layer to request that
|
/// MLME SOUNDING request primitive which is used by the next higher layer to request that
|
||||||
/// the PHY respond with channel sounding information
|
/// the PHY respond with channel sounding information
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[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 {
|
impl MacCommand for SoundingRequest {
|
||||||
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSoundingReq;
|
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSoundingReq;
|
||||||
const SIZE: usize = 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// MLME CALIBRATE request primitive which used to obtain the results of a ranging
|
/// MLME CALIBRATE request primitive which used to obtain the results of a ranging
|
||||||
/// calibration request from an RDEV
|
/// calibration request from an RDEV
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[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 {
|
impl MacCommand for CalibrateRequest {
|
||||||
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeCalibrateReq;
|
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeCalibrateReq;
|
||||||
const SIZE: usize = 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// MCPS DATA Request used for MAC data related requests from the application
|
/// MCPS DATA Request used for MAC data related requests from the application
|
||||||
@ -370,6 +368,15 @@ pub struct DataRequest {
|
|||||||
pub datrate: u8,
|
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 {
|
impl Default for DataRequest {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -397,7 +404,6 @@ impl Default for DataRequest {
|
|||||||
|
|
||||||
impl MacCommand for DataRequest {
|
impl MacCommand for DataRequest {
|
||||||
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::McpsDataReq;
|
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::McpsDataReq;
|
||||||
const SIZE: usize = 40;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// for MCPS PURGE Request used to purge an MSDU from the transaction queue
|
/// 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
|
/// the handle associated with the MSDU to be purged from the transaction
|
||||||
/// queue
|
/// queue
|
||||||
pub msdu_handle: u8,
|
pub msdu_handle: u8,
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
|
pub a_stuffing: [u8; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MacCommand for PurgeRequest {
|
impl MacCommand for PurgeRequest {
|
||||||
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::McpsPurgeReq;
|
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::McpsPurgeReq;
|
||||||
const SIZE: usize = 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// MLME ASSOCIATE Response used to initiate a response to an MLME-ASSOCIATE.indication
|
/// 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,
|
pub key_id_mode: KeyIdMode,
|
||||||
/// the index of the key to be used
|
/// the index of the key to be used
|
||||||
pub key_index: u8,
|
pub key_index: u8,
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
|
pub a_stuffing: [u8; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MacCommand for AssociateResponse {
|
impl MacCommand for AssociateResponse {
|
||||||
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeAssociateRes;
|
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeAssociateRes;
|
||||||
const SIZE: usize = 24;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// MLME ORPHAN Response used to respond to the MLME ORPHAN Indication
|
/// MLME ORPHAN Response used to respond to the MLME ORPHAN Indication
|
||||||
@ -459,9 +467,10 @@ pub struct OrphanResponse {
|
|||||||
pub key_id_mode: KeyIdMode,
|
pub key_id_mode: KeyIdMode,
|
||||||
/// the index of the key to be used
|
/// the index of the key to be used
|
||||||
pub key_index: u8,
|
pub key_index: u8,
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
|
pub a_stuffing: [u8; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MacCommand for OrphanResponse {
|
impl MacCommand for OrphanResponse {
|
||||||
const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeOrphanRes;
|
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 embassy_sync::pubsub::{PubSubChannel, Subscriber};
|
||||||
|
|
||||||
use super::helpers::to_u16;
|
use super::helpers::to_u16;
|
||||||
|
use core::mem;
|
||||||
|
|
||||||
use super::indications::{
|
use super::indications::{
|
||||||
AssociateIndication, BeaconNotifyIndication, CommStatusIndication, DataIndication, DisassociateIndication,
|
AssociateIndication, BeaconNotifyIndication, CommStatusIndication, DataIndication, DisassociateIndication,
|
||||||
DpsIndication, GtsIndication, OrphanIndication, PollIndication, SyncLossIndication,
|
DpsIndication, GtsIndication, OrphanIndication, PollIndication, SyncLossIndication,
|
||||||
@ -12,91 +14,100 @@ use super::responses::{
|
|||||||
AssociateConfirm, CalibrateConfirm, DataConfirm, DisassociateConfirm, DpsConfirm, GetConfirm, GtsConfirm,
|
AssociateConfirm, CalibrateConfirm, DataConfirm, DisassociateConfirm, DpsConfirm, GetConfirm, GtsConfirm,
|
||||||
PollConfirm, PurgeConfirm, ResetConfirm, RxEnableConfirm, ScanConfirm, SetConfirm, SoundingConfirm, StartConfirm,
|
PollConfirm, PurgeConfirm, ResetConfirm, RxEnableConfirm, ScanConfirm, SetConfirm, SoundingConfirm, StartConfirm,
|
||||||
};
|
};
|
||||||
|
use crate::evt::EvtBox;
|
||||||
use crate::mac::opcodes::OpcodeM0ToM4;
|
use crate::mac::opcodes::OpcodeM0ToM4;
|
||||||
|
use crate::sub::mac::Mac;
|
||||||
|
|
||||||
pub trait ParseableMacEvent {
|
pub(crate) trait ParseableMacEvent: Sized {
|
||||||
const SIZE: usize;
|
fn from_buffer<'a>(buf: &'a [u8]) -> Result<&'a Self, ()> {
|
||||||
|
if buf.len() < mem::size_of::<Self>() {
|
||||||
fn validate(buf: &[u8]) -> Result<(), ()> {
|
Err(())
|
||||||
if buf.len() < Self::SIZE {
|
} else {
|
||||||
return Err(());
|
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, ()>
|
pub fn mac_event<'a>(&'a self) -> Result<MacEvent<'a>, ()> {
|
||||||
where
|
let payload = self.event_box.payload();
|
||||||
Self: Sized;
|
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)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum MacEvent {
|
pub enum MacEvent<'a> {
|
||||||
MlmeAssociateCnf(AssociateConfirm),
|
MlmeAssociateCnf(&'a AssociateConfirm),
|
||||||
MlmeDisassociateCnf(DisassociateConfirm),
|
MlmeDisassociateCnf(&'a DisassociateConfirm),
|
||||||
MlmeGetCnf(GetConfirm),
|
MlmeGetCnf(&'a GetConfirm),
|
||||||
MlmeGtsCnf(GtsConfirm),
|
MlmeGtsCnf(&'a GtsConfirm),
|
||||||
MlmeResetCnf(ResetConfirm),
|
MlmeResetCnf(&'a ResetConfirm),
|
||||||
MlmeRxEnableCnf(RxEnableConfirm),
|
MlmeRxEnableCnf(&'a RxEnableConfirm),
|
||||||
MlmeScanCnf(ScanConfirm),
|
MlmeScanCnf(&'a ScanConfirm),
|
||||||
MlmeSetCnf(SetConfirm),
|
MlmeSetCnf(&'a SetConfirm),
|
||||||
MlmeStartCnf(StartConfirm),
|
MlmeStartCnf(&'a StartConfirm),
|
||||||
MlmePollCnf(PollConfirm),
|
MlmePollCnf(&'a PollConfirm),
|
||||||
MlmeDpsCnf(DpsConfirm),
|
MlmeDpsCnf(&'a DpsConfirm),
|
||||||
MlmeSoundingCnf(SoundingConfirm),
|
MlmeSoundingCnf(&'a SoundingConfirm),
|
||||||
MlmeCalibrateCnf(CalibrateConfirm),
|
MlmeCalibrateCnf(&'a CalibrateConfirm),
|
||||||
McpsDataCnf(DataConfirm),
|
McpsDataCnf(&'a DataConfirm),
|
||||||
McpsPurgeCnf(PurgeConfirm),
|
McpsPurgeCnf(&'a PurgeConfirm),
|
||||||
MlmeAssociateInd(AssociateIndication),
|
MlmeAssociateInd(&'a AssociateIndication),
|
||||||
MlmeDisassociateInd(DisassociateIndication),
|
MlmeDisassociateInd(&'a DisassociateIndication),
|
||||||
MlmeBeaconNotifyInd(BeaconNotifyIndication),
|
MlmeBeaconNotifyInd(&'a BeaconNotifyIndication),
|
||||||
MlmeCommStatusInd(CommStatusIndication),
|
MlmeCommStatusInd(&'a CommStatusIndication),
|
||||||
MlmeGtsInd(GtsIndication),
|
MlmeGtsInd(&'a GtsIndication),
|
||||||
MlmeOrphanInd(OrphanIndication),
|
MlmeOrphanInd(&'a OrphanIndication),
|
||||||
MlmeSyncLossInd(SyncLossIndication),
|
MlmeSyncLossInd(&'a SyncLossIndication),
|
||||||
MlmeDpsInd(DpsIndication),
|
MlmeDpsInd(&'a DpsIndication),
|
||||||
McpsDataInd(DataIndication),
|
McpsDataInd(&'a DataIndication),
|
||||||
MlmePollInd(PollIndication),
|
MlmePollInd(&'a 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)?)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO this PubSub can probably be replaced with shared memory to make it a bit more efficient.
|
// 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::consts::MAX_PENDING_ADDRESS;
|
||||||
use super::event::ParseableMacEvent;
|
use super::event::ParseableMacEvent;
|
||||||
use super::helpers::to_u32;
|
|
||||||
use super::typedefs::{
|
use super::typedefs::{
|
||||||
AddressMode, Capabilities, DisassociationReason, KeyIdMode, MacAddress, MacChannel, MacStatus, PanDescriptor,
|
AddressMode, Capabilities, DisassociationReason, KeyIdMode, MacAddress, MacChannel, MacStatus, PanDescriptor,
|
||||||
PanId, SecurityLevel,
|
PanId, SecurityLevel,
|
||||||
@ -8,6 +9,7 @@ use super::typedefs::{
|
|||||||
|
|
||||||
/// MLME ASSOCIATE Indication which will be used by the MAC
|
/// MLME ASSOCIATE Indication which will be used by the MAC
|
||||||
/// to indicate the reception of an association request command
|
/// to indicate the reception of an association request command
|
||||||
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct AssociateIndication {
|
pub struct AssociateIndication {
|
||||||
/// Extended address of the device requesting association
|
/// Extended address of the device requesting association
|
||||||
@ -24,25 +26,11 @@ pub struct AssociateIndication {
|
|||||||
pub key_source: [u8; 8],
|
pub key_source: [u8; 8],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for AssociateIndication {
|
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]],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// MLME DISASSOCIATE indication which will be used to send
|
/// MLME DISASSOCIATE indication which will be used to send
|
||||||
/// disassociation indication to the application.
|
/// disassociation indication to the application.
|
||||||
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct DisassociateIndication {
|
pub struct DisassociateIndication {
|
||||||
/// Extended address of the device requesting association
|
/// Extended address of the device requesting association
|
||||||
@ -59,25 +47,11 @@ pub struct DisassociateIndication {
|
|||||||
pub key_source: [u8; 8],
|
pub key_source: [u8; 8],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for DisassociateIndication {
|
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]],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// MLME BEACON NOTIIFY Indication which is used to send parameters contained
|
/// MLME BEACON NOTIIFY Indication which is used to send parameters contained
|
||||||
/// within a beacon frame received by the MAC to the application
|
/// within a beacon frame received by the MAC to the application
|
||||||
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct BeaconNotifyIndication {
|
pub struct BeaconNotifyIndication {
|
||||||
/// he set of octets comprising the beacon payload to be transferred
|
/// he set of octets comprising the beacon payload to be transferred
|
||||||
@ -95,36 +69,10 @@ pub struct BeaconNotifyIndication {
|
|||||||
pub sdu_length: u8,
|
pub sdu_length: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for BeaconNotifyIndication {
|
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],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// MLME COMM STATUS Indication which is used by the MAC to indicate a communications status
|
/// MLME COMM STATUS Indication which is used by the MAC to indicate a communications status
|
||||||
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct CommStatusIndication {
|
pub struct CommStatusIndication {
|
||||||
/// The 16-bit PAN identifier of the device from which the frame
|
/// The 16-bit PAN identifier of the device from which the frame
|
||||||
@ -150,54 +98,11 @@ pub struct CommStatusIndication {
|
|||||||
pub key_source: [u8; 8],
|
pub key_source: [u8; 8],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for CommStatusIndication {
|
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]],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// MLME GTS Indication indicates that a GTS has been allocated or that a
|
/// MLME GTS Indication indicates that a GTS has been allocated or that a
|
||||||
/// previously allocated GTS has been deallocated
|
/// previously allocated GTS has been deallocated
|
||||||
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct GtsIndication {
|
pub struct GtsIndication {
|
||||||
/// The short address of the device that has been allocated or deallocated a GTS
|
/// 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,
|
pub key_id_mode: KeyIdMode,
|
||||||
/// Index of the key to be used
|
/// Index of the key to be used
|
||||||
pub key_index: u8,
|
pub key_index: u8,
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
|
a_stuffing: [u8; 2],
|
||||||
/// Originator of the key to be used
|
/// Originator of the key to be used
|
||||||
pub key_source: [u8; 8],
|
pub key_source: [u8; 8],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for GtsIndication {
|
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]],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// MLME ORPHAN Indication which is used by the coordinator to notify the
|
/// MLME ORPHAN Indication which is used by the coordinator to notify the
|
||||||
/// application of the presence of an orphaned device
|
/// application of the presence of an orphaned device
|
||||||
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct OrphanIndication {
|
pub struct OrphanIndication {
|
||||||
/// Extended address of the orphaned device
|
/// Extended address of the orphaned device
|
||||||
@ -246,27 +138,15 @@ pub struct OrphanIndication {
|
|||||||
pub key_id_mode: KeyIdMode,
|
pub key_id_mode: KeyIdMode,
|
||||||
/// Index of the key used by the originator of the received frame
|
/// Index of the key used by the originator of the received frame
|
||||||
pub key_index: u8,
|
pub key_index: u8,
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
|
a_stuffing: [u8; 1],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for OrphanIndication {
|
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
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// MLME SYNC LOSS Indication which is used by the MAC to indicate the loss
|
/// MLME SYNC LOSS Indication which is used by the MAC to indicate the loss
|
||||||
/// of synchronization with the coordinator
|
/// of synchronization with the coordinator
|
||||||
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct SyncLossIndication {
|
pub struct SyncLossIndication {
|
||||||
/// The PAN identifier with which the device lost synchronization or to which it was realigned
|
/// 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],
|
pub key_source: [u8; 8],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for SyncLossIndication {
|
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]],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// MLME DPS Indication which indicates the expiration of the DPSIndexDuration
|
/// MLME DPS Indication which indicates the expiration of the DPSIndexDuration
|
||||||
/// and the resetting of the DPS values in the PHY
|
/// and the resetting of the DPS values in the PHY
|
||||||
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct DpsIndication;
|
pub struct DpsIndication {
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
impl ParseableMacEvent for DpsIndication {
|
a_stuffing: [u8; 4],
|
||||||
const SIZE: usize = 4;
|
|
||||||
|
|
||||||
fn try_parse(buf: &[u8]) -> Result<Self, ()> {
|
|
||||||
Self::validate(buf)?;
|
|
||||||
|
|
||||||
Ok(Self)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ParseableMacEvent for DpsIndication {}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
#[repr(C, align(8))]
|
|
||||||
pub struct DataIndication {
|
pub struct DataIndication {
|
||||||
/// Pointer to the set of octets forming the MSDU being indicated
|
/// Pointer to the set of octets forming the MSDU being indicated
|
||||||
pub msdu_ptr: *const u8,
|
pub msdu_ptr: *const u8,
|
||||||
@ -347,9 +206,9 @@ pub struct DataIndication {
|
|||||||
/// The time, in symbols, at which the data were received
|
/// The time, in symbols, at which the data were received
|
||||||
pub time_stamp: [u8; 4],
|
pub time_stamp: [u8; 4],
|
||||||
/// The security level purportedly used by the received data frame
|
/// 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
|
/// 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
|
/// The originator of the key
|
||||||
pub key_source: [u8; 8],
|
pub key_source: [u8; 8],
|
||||||
/// The index of the key
|
/// The index of the key
|
||||||
@ -374,68 +233,17 @@ pub struct DataIndication {
|
|||||||
pub rssi: u8,
|
pub rssi: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for DataIndication {
|
impl ParseableMacEvent for DataIndication {}
|
||||||
const SIZE: usize = 68;
|
|
||||||
|
|
||||||
fn try_parse(buf: &[u8]) -> Result<Self, ()> {
|
impl DataIndication {
|
||||||
Self::validate(buf)?;
|
pub fn payload<'a>(&'a self) -> &'a [u8] {
|
||||||
|
unsafe { slice::from_raw_parts(self.msdu_ptr, self.msdu_length as usize) }
|
||||||
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],
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// MLME POLL Indication which will be used for indicating the Data Request
|
/// MLME POLL Indication which will be used for indicating the Data Request
|
||||||
/// reception to upper layer as defined in Zigbee r22 - D.8.2
|
/// reception to upper layer as defined in Zigbee r22 - D.8.2
|
||||||
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct PollIndication {
|
pub struct PollIndication {
|
||||||
/// addressing mode used
|
/// addressing mode used
|
||||||
@ -444,27 +252,4 @@ pub struct PollIndication {
|
|||||||
pub request_address: MacAddress,
|
pub request_address: MacAddress,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for PollIndication {
|
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,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -2,7 +2,6 @@ pub mod commands;
|
|||||||
mod consts;
|
mod consts;
|
||||||
pub mod control;
|
pub mod control;
|
||||||
pub mod event;
|
pub mod event;
|
||||||
mod helpers;
|
|
||||||
pub mod indications;
|
pub mod indications;
|
||||||
mod ioctl;
|
mod ioctl;
|
||||||
mod macros;
|
mod macros;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use super::consts::{MAX_ED_SCAN_RESULTS_SUPPORTED, MAX_PAN_DESC_SUPPORTED, MAX_SOUNDING_LIST_SUPPORTED};
|
use super::consts::{MAX_ED_SCAN_RESULTS_SUPPORTED, MAX_PAN_DESC_SUPPORTED, MAX_SOUNDING_LIST_SUPPORTED};
|
||||||
use super::event::ParseableMacEvent;
|
use super::event::ParseableMacEvent;
|
||||||
use super::helpers::to_u32;
|
|
||||||
use super::typedefs::{
|
use super::typedefs::{
|
||||||
AddressMode, AssociationStatus, KeyIdMode, MacAddress, MacStatus, PanDescriptor, PanId, PibId, ScanType,
|
AddressMode, AssociationStatus, KeyIdMode, MacAddress, MacStatus, PanDescriptor, PanId, PibId, ScanType,
|
||||||
SecurityLevel,
|
SecurityLevel,
|
||||||
@ -8,6 +7,7 @@ use super::typedefs::{
|
|||||||
|
|
||||||
/// MLME ASSOCIATE Confirm used to inform of the initiating device whether
|
/// MLME ASSOCIATE Confirm used to inform of the initiating device whether
|
||||||
/// its request to associate was successful or unsuccessful
|
/// its request to associate was successful or unsuccessful
|
||||||
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct AssociateConfirm {
|
pub struct AssociateConfirm {
|
||||||
/// short address allocated by the coordinator on successful association
|
/// short address allocated by the coordinator on successful association
|
||||||
@ -22,26 +22,14 @@ pub struct AssociateConfirm {
|
|||||||
pub key_id_mode: KeyIdMode,
|
pub key_id_mode: KeyIdMode,
|
||||||
/// the index of the key to be used
|
/// the index of the key to be used
|
||||||
pub key_index: u8,
|
pub key_index: u8,
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
|
a_stuffing: [u8; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for AssociateConfirm {
|
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],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// MLME DISASSOCIATE Confirm used to send disassociation Confirmation to the application.
|
/// MLME DISASSOCIATE Confirm used to send disassociation Confirmation to the application.
|
||||||
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct DisassociateConfirm {
|
pub struct DisassociateConfirm {
|
||||||
/// status of the disassociation attempt
|
/// status of the disassociation attempt
|
||||||
@ -54,34 +42,10 @@ pub struct DisassociateConfirm {
|
|||||||
pub device_address: MacAddress,
|
pub device_address: MacAddress,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for DisassociateConfirm {
|
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,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// MLME GET Confirm which requests information about a given PIB attribute
|
/// MLME GET Confirm which requests information about a given PIB attribute
|
||||||
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct GetConfirm {
|
pub struct GetConfirm {
|
||||||
/// The pointer to the value of the PIB attribute attempted to read
|
/// The pointer to the value of the PIB attribute attempted to read
|
||||||
@ -92,88 +56,54 @@ pub struct GetConfirm {
|
|||||||
pub pib_attribute: PibId,
|
pub pib_attribute: PibId,
|
||||||
/// The lenght of the PIB attribute Value return
|
/// The lenght of the PIB attribute Value return
|
||||||
pub pib_attribute_value_len: u8,
|
pub pib_attribute_value_len: u8,
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
|
a_stuffing: [u8; 1],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for GetConfirm {
|
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],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// MLME GTS Confirm which eports the results of a request to allocate a new GTS
|
/// MLME GTS Confirm which eports the results of a request to allocate a new GTS
|
||||||
/// or to deallocate an existing GTS
|
/// or to deallocate an existing GTS
|
||||||
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct GtsConfirm {
|
pub struct GtsConfirm {
|
||||||
/// The characteristics of the GTS
|
/// The characteristics of the GTS
|
||||||
pub gts_characteristics: u8,
|
pub gts_characteristics: u8,
|
||||||
/// The status of the GTS reques
|
/// The status of the GTS reques
|
||||||
pub status: MacStatus,
|
pub status: MacStatus,
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
|
a_stuffing: [u8; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for GtsConfirm {
|
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])?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// MLME RESET Confirm which is used to report the results of the reset operation
|
/// MLME RESET Confirm which is used to report the results of the reset operation
|
||||||
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct ResetConfirm {
|
pub struct ResetConfirm {
|
||||||
/// The result of the reset operation
|
/// The result of the reset operation
|
||||||
status: MacStatus,
|
status: MacStatus,
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
|
a_stuffing: [u8; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for ResetConfirm {
|
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])?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// MLME RX ENABLE Confirm which is used to report the results of the attempt
|
/// MLME RX ENABLE Confirm which is used to report the results of the attempt
|
||||||
/// to enable or disable the receiver
|
/// to enable or disable the receiver
|
||||||
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct RxEnableConfirm {
|
pub struct RxEnableConfirm {
|
||||||
/// Result of the request to enable or disable the receiver
|
/// Result of the request to enable or disable the receiver
|
||||||
status: MacStatus,
|
status: MacStatus,
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
|
a_stuffing: [u8; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for RxEnableConfirm {
|
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])?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// MLME SCAN Confirm which is used to report the result of the channel scan request
|
/// MLME SCAN Confirm which is used to report the result of the channel scan request
|
||||||
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct ScanConfirm {
|
pub struct ScanConfirm {
|
||||||
/// Status of the scan request
|
/// Status of the scan request
|
||||||
@ -196,150 +126,81 @@ pub struct ScanConfirm {
|
|||||||
pub uwb_energy_detect_list: [u8; MAX_ED_SCAN_RESULTS_SUPPORTED],
|
pub uwb_energy_detect_list: [u8; MAX_ED_SCAN_RESULTS_SUPPORTED],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for ScanConfirm {
|
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,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// MLME SET Confirm which reports the result of an attempt to write a value to a PIB attribute
|
/// 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))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct SetConfirm {
|
pub struct SetConfirm {
|
||||||
/// The result of the set operation
|
/// The result of the set operation
|
||||||
pub status: MacStatus,
|
pub status: MacStatus,
|
||||||
/// The name of the PIB attribute that was written
|
/// The name of the PIB attribute that was written
|
||||||
pub pin_attribute: PibId,
|
pub pin_attribute: PibId,
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
|
a_stuffing: [u8; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for SetConfirm {
|
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])?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// MLME START Confirm which is used to report the results of the attempt to
|
/// MLME START Confirm which is used to report the results of the attempt to
|
||||||
/// start using a new superframe configuration
|
/// start using a new superframe configuration
|
||||||
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct StartConfirm {
|
pub struct StartConfirm {
|
||||||
/// Result of the attempt to start using an updated superframe configuration
|
/// Result of the attempt to start using an updated superframe configuration
|
||||||
pub status: MacStatus,
|
pub status: MacStatus,
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
|
a_stuffing: [u8; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for StartConfirm {
|
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])?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// MLME POLL Confirm which is used to report the result of a request to poll the coordinator for data
|
/// 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))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct PollConfirm {
|
pub struct PollConfirm {
|
||||||
/// The status of the data request
|
/// The status of the data request
|
||||||
pub status: MacStatus,
|
pub status: MacStatus,
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
|
a_stuffing: [u8; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for PollConfirm {
|
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])?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// MLME DPS Confirm which reports the results of the attempt to enable or disable the DPS
|
/// 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))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct DpsConfirm {
|
pub struct DpsConfirm {
|
||||||
/// The status of the DPS request
|
/// The status of the DPS request
|
||||||
pub status: MacStatus,
|
pub status: MacStatus,
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
|
a_stuffing: [u8; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for DpsConfirm {
|
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])?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// MLME SOUNDING Confirm which reports the result of a request to the PHY to provide
|
/// MLME SOUNDING Confirm which reports the result of a request to the PHY to provide
|
||||||
/// channel sounding information
|
/// channel sounding information
|
||||||
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct SoundingConfirm {
|
pub struct SoundingConfirm {
|
||||||
/// Results of the sounding measurement
|
/// Results of the sounding measurement
|
||||||
sounding_list: [u8; MAX_SOUNDING_LIST_SUPPORTED],
|
sounding_list: [u8; MAX_SOUNDING_LIST_SUPPORTED],
|
||||||
|
|
||||||
|
status: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for SoundingConfirm {
|
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 })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// MLME CALIBRATE Confirm which reports the result of a request to the PHY
|
/// MLME CALIBRATE Confirm which reports the result of a request to the PHY
|
||||||
/// to provide internal propagation path information
|
/// to provide internal propagation path information
|
||||||
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct CalibrateConfirm {
|
pub struct CalibrateConfirm {
|
||||||
/// The status of the attempt to return sounding data
|
/// The status of the attempt to return sounding data
|
||||||
pub status: MacStatus,
|
pub status: MacStatus,
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
|
a_stuffing: [u8; 3],
|
||||||
/// A count of the propagation time from the ranging counter
|
/// A count of the propagation time from the ranging counter
|
||||||
/// to the transmit antenna
|
/// to the transmit antenna
|
||||||
pub cal_tx_rmaker_offset: u32,
|
pub cal_tx_rmaker_offset: u32,
|
||||||
@ -348,23 +209,11 @@ pub struct CalibrateConfirm {
|
|||||||
pub cal_rx_rmaker_offset: u32,
|
pub cal_rx_rmaker_offset: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for CalibrateConfirm {
|
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]),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// MCPS DATA Confirm which will be used for reporting the results of
|
/// MCPS DATA Confirm which will be used for reporting the results of
|
||||||
/// MAC data related requests from the application
|
/// MAC data related requests from the application
|
||||||
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct DataConfirm {
|
pub struct DataConfirm {
|
||||||
/// The handle associated with the MSDU being confirmed
|
/// The handle associated with the MSDU being confirmed
|
||||||
@ -387,47 +236,23 @@ pub struct DataConfirm {
|
|||||||
pub ranging_offset: u32,
|
pub ranging_offset: u32,
|
||||||
/// The FoM characterizing the ranging measurement
|
/// The FoM characterizing the ranging measurement
|
||||||
pub ranging_fom: u8,
|
pub ranging_fom: u8,
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
|
a_stuffing: [u8; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for DataConfirm {
|
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],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// MCPS PURGE Confirm which will be used by the MAC to notify the application of
|
/// 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
|
/// the status of its request to purge an MSDU from the transaction queue
|
||||||
|
#[repr(C)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct PurgeConfirm {
|
pub struct PurgeConfirm {
|
||||||
/// Handle associated with the MSDU requested to be purged from the transaction queue
|
/// Handle associated with the MSDU requested to be purged from the transaction queue
|
||||||
pub msdu_handle: u8,
|
pub msdu_handle: u8,
|
||||||
/// The status of the request
|
/// The status of the request
|
||||||
pub status: MacStatus,
|
pub status: MacStatus,
|
||||||
|
/// byte stuffing to keep 32 bit alignment
|
||||||
|
a_stuffing: [u8; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseableMacEvent for PurgeConfirm {
|
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])?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -37,9 +37,11 @@ numeric_enum! {
|
|||||||
numeric_enum! {
|
numeric_enum! {
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
/// this enum contains all the MAC PIB Ids
|
/// this enum contains all the MAC PIB Ids
|
||||||
|
#[derive(Default)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum PibId {
|
pub enum PibId {
|
||||||
// PHY
|
// PHY
|
||||||
|
#[default]
|
||||||
CurrentChannel = 0x00,
|
CurrentChannel = 0x00,
|
||||||
ChannelsSupported = 0x01,
|
ChannelsSupported = 0x01,
|
||||||
TransmitPower = 0x02,
|
TransmitPower = 0x02,
|
||||||
|
@ -12,7 +12,7 @@ use crate::cmd::CmdPacket;
|
|||||||
use crate::consts::TlPacketType;
|
use crate::consts::TlPacketType;
|
||||||
use crate::evt::{EvtBox, EvtPacket};
|
use crate::evt::{EvtBox, EvtPacket};
|
||||||
use crate::mac::commands::MacCommand;
|
use crate::mac::commands::MacCommand;
|
||||||
use crate::mac::event::MacEvent;
|
use crate::mac::event::Event;
|
||||||
use crate::mac::typedefs::MacError;
|
use crate::mac::typedefs::MacError;
|
||||||
use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER};
|
use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER};
|
||||||
use crate::{channels, evt};
|
use crate::{channels, evt};
|
||||||
@ -85,12 +85,7 @@ impl Mac {
|
|||||||
where
|
where
|
||||||
T: MacCommand,
|
T: MacCommand,
|
||||||
{
|
{
|
||||||
let mut payload = [0u8; MAX_PACKET_SIZE];
|
let response = self.tl_write_and_get_response(T::OPCODE as u16, cmd.payload()).await;
|
||||||
cmd.copy_into_slice(&mut payload);
|
|
||||||
|
|
||||||
let response = self
|
|
||||||
.tl_write_and_get_response(T::OPCODE as u16, &payload[..T::SIZE])
|
|
||||||
.await;
|
|
||||||
|
|
||||||
if response == 0x00 {
|
if response == 0x00 {
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -99,16 +94,11 @@ impl Mac {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn read(&self) -> Result<MacEvent, ()> {
|
pub async fn read(&self) -> Event {
|
||||||
let evt_box = self.tl_read().await;
|
Event::new(self.tl_read().await)
|
||||||
let payload = evt_box.payload();
|
|
||||||
|
|
||||||
MacEvent::try_from(payload)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_PACKET_SIZE: usize = 255;
|
|
||||||
|
|
||||||
impl evt::MemoryManager for Mac {
|
impl evt::MemoryManager for Mac {
|
||||||
/// SAFETY: passing a pointer to something other than a managed event packet is UB
|
/// SAFETY: passing a pointer to something other than a managed event packet is UB
|
||||||
unsafe fn drop_event_packet(_: *mut EvtPacket) {
|
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 }
|
byte-slice-cast = { version = "1.2.0", default-features = false }
|
||||||
smart-leds = "0.3.0"
|
smart-leds = "0.3.0"
|
||||||
heapless = "0.7.15"
|
heapless = "0.7.15"
|
||||||
|
usbd-hid = "0.6.1"
|
||||||
|
|
||||||
embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" }
|
embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" }
|
||||||
embedded-hal-async = "0.2.0-alpha.2"
|
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");
|
info!("resetting");
|
||||||
mbox.mac_subsystem
|
mbox.mac_subsystem
|
||||||
.send_command(&ResetRequest { set_default_pib: true })
|
.send_command(&ResetRequest {
|
||||||
|
set_default_pib: true,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.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");
|
info!("setting extended address");
|
||||||
let extended_address: u64 = 0xACDE480000000001;
|
let extended_address: u64 = 0xACDE480000000001;
|
||||||
@ -82,8 +87,10 @@ async fn main(spawner: Spawner) {
|
|||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.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");
|
info!("setting short address");
|
||||||
let short_address: u16 = 0x1122;
|
let short_address: u16 = 0x1122;
|
||||||
@ -94,8 +101,10 @@ async fn main(spawner: Spawner) {
|
|||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.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");
|
info!("setting association permit");
|
||||||
let association_permit: bool = true;
|
let association_permit: bool = true;
|
||||||
@ -106,8 +115,10 @@ async fn main(spawner: Spawner) {
|
|||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.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");
|
info!("setting TX power");
|
||||||
let transmit_power: i8 = 2;
|
let transmit_power: i8 = 2;
|
||||||
@ -118,8 +129,10 @@ async fn main(spawner: Spawner) {
|
|||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.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");
|
info!("starting FFD device");
|
||||||
mbox.mac_subsystem
|
mbox.mac_subsystem
|
||||||
@ -134,8 +147,10 @@ async fn main(spawner: Spawner) {
|
|||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.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");
|
info!("setting RX on when idle");
|
||||||
let rx_on_while_idle: bool = true;
|
let rx_on_while_idle: bool = true;
|
||||||
@ -146,14 +161,17 @@ async fn main(spawner: Spawner) {
|
|||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.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 {
|
loop {
|
||||||
let evt = mbox.mac_subsystem.read().await;
|
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 {
|
match evt {
|
||||||
MacEvent::MlmeAssociateInd(association) => mbox
|
MacEvent::MlmeAssociateInd(association) => mbox
|
||||||
.mac_subsystem
|
.mac_subsystem
|
||||||
@ -167,17 +185,22 @@ async fn main(spawner: Spawner) {
|
|||||||
.await
|
.await
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
MacEvent::McpsDataInd(data_ind) => {
|
MacEvent::McpsDataInd(data_ind) => {
|
||||||
let data_addr = data_ind.msdu_ptr;
|
let payload = data_ind.payload();
|
||||||
let mut data = [0u8; 256];
|
let ref_payload = b"Hello from embassy!";
|
||||||
unsafe { data_addr.copy_to(&mut data as *mut _, data_ind.msdu_length as usize) }
|
info!("{}", payload);
|
||||||
info!("{}", data[..data_ind.msdu_length as usize]);
|
|
||||||
|
|
||||||
if &data[..data_ind.msdu_length as usize] == b"Hello from embassy!" {
|
if payload == ref_payload {
|
||||||
info!("success");
|
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");
|
info!("resetting");
|
||||||
mbox.mac_subsystem
|
mbox.mac_subsystem
|
||||||
.send_command(&ResetRequest { set_default_pib: true })
|
.send_command(&ResetRequest {
|
||||||
|
set_default_pib: true,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.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");
|
info!("setting extended address");
|
||||||
let extended_address: u64 = 0xACDE480000000002;
|
let extended_address: u64 = 0xACDE480000000002;
|
||||||
@ -84,24 +89,30 @@ async fn main(spawner: Spawner) {
|
|||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.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");
|
info!("getting extended address");
|
||||||
mbox.mac_subsystem
|
mbox.mac_subsystem
|
||||||
.send_command(&GetRequest {
|
.send_command(&GetRequest {
|
||||||
pib_attribute: PibId::ExtendedAddress,
|
pib_attribute: PibId::ExtendedAddress,
|
||||||
|
..Default::default()
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.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 evt = mbox.mac_subsystem.read().await;
|
||||||
let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) };
|
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);
|
info!("{}", a);
|
||||||
mbox.mac_subsystem.send_command(&a).await.unwrap();
|
mbox.mac_subsystem.send_command(&a).await.unwrap();
|
||||||
let evt = mbox.mac_subsystem.read().await;
|
let short_addr = {
|
||||||
info!("{:#x}", evt);
|
let evt = mbox.mac_subsystem.read().await;
|
||||||
|
info!("{:#x}", evt.mac_event());
|
||||||
|
|
||||||
let short_addr = if let Ok(MacEvent::MlmeAssociateCnf(conf)) = evt {
|
if let Ok(MacEvent::MlmeAssociateCnf(conf)) = evt.mac_event() {
|
||||||
conf.assoc_short_address
|
conf.assoc_short_address
|
||||||
} else {
|
} else {
|
||||||
defmt::panic!()
|
defmt::panic!()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
info!("setting short address");
|
info!("setting short address");
|
||||||
@ -137,34 +150,37 @@ async fn main(spawner: Spawner) {
|
|||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.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");
|
info!("sending data");
|
||||||
let mut data_buffer = [0u8; 256];
|
|
||||||
let data = b"Hello from embassy!";
|
let data = b"Hello from embassy!";
|
||||||
data_buffer[..data.len()].copy_from_slice(data);
|
|
||||||
mbox.mac_subsystem
|
mbox.mac_subsystem
|
||||||
.send_command(&DataRequest {
|
.send_command(
|
||||||
src_addr_mode: AddressMode::Short,
|
DataRequest {
|
||||||
dst_addr_mode: AddressMode::Short,
|
src_addr_mode: AddressMode::Short,
|
||||||
dst_pan_id: PanId([0x1A, 0xAA]),
|
dst_addr_mode: AddressMode::Short,
|
||||||
dst_address: MacAddress::BROADCAST,
|
dst_pan_id: PanId([0x1A, 0xAA]),
|
||||||
msdu_handle: 0x02,
|
dst_address: MacAddress::BROADCAST,
|
||||||
ack_tx: 0x00,
|
msdu_handle: 0x02,
|
||||||
gts_tx: false,
|
ack_tx: 0x00,
|
||||||
msdu_ptr: &data_buffer as *const _ as *const u8,
|
gts_tx: false,
|
||||||
msdu_length: data.len() as u8,
|
security_level: SecurityLevel::Unsecure,
|
||||||
security_level: SecurityLevel::Unsecure,
|
..Default::default()
|
||||||
..Default::default()
|
}
|
||||||
})
|
.set_buffer(data),
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let evt = mbox.mac_subsystem.read().await;
|
{
|
||||||
info!("{:#x}", evt);
|
let evt = mbox.mac_subsystem.read().await;
|
||||||
|
info!("{:#x}", evt.mac_event());
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let evt = mbox.mac_subsystem.read().await;
|
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");
|
info!("resetting");
|
||||||
mbox.mac_subsystem
|
mbox.mac_subsystem
|
||||||
.send_command(&ResetRequest { set_default_pib: true })
|
.send_command(&ResetRequest {
|
||||||
|
set_default_pib: true,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.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");
|
info!("setting extended address");
|
||||||
let extended_address: u64 = 0xACDE480000000002;
|
let extended_address: u64 = 0xACDE480000000002;
|
||||||
@ -64,24 +69,29 @@ async fn main(spawner: Spawner) {
|
|||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.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");
|
info!("getting extended address");
|
||||||
mbox.mac_subsystem
|
mbox.mac_subsystem
|
||||||
.send_command(&GetRequest {
|
.send_command(&GetRequest {
|
||||||
pib_attribute: PibId::ExtendedAddress,
|
pib_attribute: PibId::ExtendedAddress,
|
||||||
|
..Default::default()
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.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 let Ok(MacEvent::MlmeGetCnf(evt)) = evt.mac_event() {
|
||||||
if evt.pib_attribute_value_len == 8 {
|
if evt.pib_attribute_value_len == 8 {
|
||||||
let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) };
|
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);
|
info!("{}", a);
|
||||||
mbox.mac_subsystem.send_command(&a).await.unwrap();
|
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");
|
info!("Test OK");
|
||||||
cortex_m::asm::bkpt();
|
cortex_m::asm::bkpt();
|
||||||
|
Loading…
Reference in New Issue
Block a user