embassy/embassy-stm32-wpan/src/mac/event.rs
2023-07-20 20:51:49 -05:00

154 lines
6.8 KiB
Rust

use core::{mem, ptr};
use super::indications::{
AssociateIndication, BeaconNotifyIndication, CommStatusIndication, DataIndication, DisassociateIndication,
DpsIndication, GtsIndication, OrphanIndication, PollIndication, SyncLossIndication,
};
use super::responses::{
AssociateConfirm, CalibrateConfirm, DataConfirm, DisassociateConfirm, DpsConfirm, GetConfirm, GtsConfirm,
PollConfirm, PurgeConfirm, ResetConfirm, RxEnableConfirm, ScanConfirm, SetConfirm, SoundingConfirm, StartConfirm,
};
use crate::evt::{EvtBox, MemoryManager};
use crate::mac::opcodes::OpcodeM0ToM4;
use crate::sub::mac::{self, Mac};
pub(crate) trait ParseableMacEvent: Sized {
fn from_buffer<'a>(buf: &'a [u8]) -> Result<&'a Self, ()> {
if buf.len() < mem::size_of::<Self>() {
Err(())
} else {
Ok(unsafe { &*(buf as *const _ as *const Self) })
}
}
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug)]
pub enum MacEvent<'a> {
MlmeAssociateCnf(&'a AssociateConfirm),
MlmeDisassociateCnf(&'a DisassociateConfirm),
MlmeGetCnf(&'a GetConfirm),
MlmeGtsCnf(&'a GtsConfirm),
MlmeResetCnf(&'a ResetConfirm),
MlmeRxEnableCnf(&'a RxEnableConfirm),
MlmeScanCnf(&'a ScanConfirm),
MlmeSetCnf(&'a SetConfirm),
MlmeStartCnf(&'a StartConfirm),
MlmePollCnf(&'a PollConfirm),
MlmeDpsCnf(&'a DpsConfirm),
MlmeSoundingCnf(&'a SoundingConfirm),
MlmeCalibrateCnf(&'a CalibrateConfirm),
McpsDataCnf(&'a DataConfirm),
McpsPurgeCnf(&'a PurgeConfirm),
MlmeAssociateInd(&'a AssociateIndication),
MlmeDisassociateInd(&'a DisassociateIndication),
MlmeBeaconNotifyInd(&'a BeaconNotifyIndication),
MlmeCommStatusInd(&'a CommStatusIndication),
MlmeGtsInd(&'a GtsIndication),
MlmeOrphanInd(&'a OrphanIndication),
MlmeSyncLossInd(&'a SyncLossIndication),
MlmeDpsInd(&'a DpsIndication),
McpsDataInd(&'a DataIndication),
MlmePollInd(&'a PollIndication),
}
impl<'a> MacEvent<'a> {
pub(crate) fn new(event_box: EvtBox<Mac>) -> Result<Self, ()> {
let payload = event_box.payload();
let opcode = u16::from_le_bytes(payload[0..2].try_into().unwrap());
let opcode = OpcodeM0ToM4::try_from(opcode)?;
let buf = &payload[2..];
// To avoid re-parsing the opcode, we store the result of the parse
// this requires use of unsafe because rust cannot assume that a reference will become
// invalid when the underlying result is moved. However, because we refer to a "heap"
// allocation, the underlying reference will not move until the struct is dropped.
let mac_event = match opcode {
OpcodeM0ToM4::MlmeAssociateCnf => {
MacEvent::MlmeAssociateCnf(unsafe { &*(AssociateConfirm::from_buffer(buf)? as *const _) })
}
OpcodeM0ToM4::MlmeDisassociateCnf => {
MacEvent::MlmeDisassociateCnf(unsafe { &*(DisassociateConfirm::from_buffer(buf)? as *const _) })
}
OpcodeM0ToM4::MlmeGetCnf => MacEvent::MlmeGetCnf(unsafe { &*(GetConfirm::from_buffer(buf)? as *const _) }),
OpcodeM0ToM4::MlmeGtsCnf => MacEvent::MlmeGtsCnf(unsafe { &*(GtsConfirm::from_buffer(buf)? as *const _) }),
OpcodeM0ToM4::MlmeResetCnf => {
MacEvent::MlmeResetCnf(unsafe { &*(ResetConfirm::from_buffer(buf)? as *const _) })
}
OpcodeM0ToM4::MlmeRxEnableCnf => {
MacEvent::MlmeRxEnableCnf(unsafe { &*(RxEnableConfirm::from_buffer(buf)? as *const _) })
}
OpcodeM0ToM4::MlmeScanCnf => {
MacEvent::MlmeScanCnf(unsafe { &*(ScanConfirm::from_buffer(buf)? as *const _) })
}
OpcodeM0ToM4::MlmeSetCnf => MacEvent::MlmeSetCnf(unsafe { &*(SetConfirm::from_buffer(buf)? as *const _) }),
OpcodeM0ToM4::MlmeStartCnf => {
MacEvent::MlmeStartCnf(unsafe { &*(StartConfirm::from_buffer(buf)? as *const _) })
}
OpcodeM0ToM4::MlmePollCnf => {
MacEvent::MlmePollCnf(unsafe { &*(PollConfirm::from_buffer(buf)? as *const _) })
}
OpcodeM0ToM4::MlmeDpsCnf => MacEvent::MlmeDpsCnf(unsafe { &*(DpsConfirm::from_buffer(buf)? as *const _) }),
OpcodeM0ToM4::MlmeSoundingCnf => {
MacEvent::MlmeSoundingCnf(unsafe { &*(SoundingConfirm::from_buffer(buf)? as *const _) })
}
OpcodeM0ToM4::MlmeCalibrateCnf => {
MacEvent::MlmeCalibrateCnf(unsafe { &*(CalibrateConfirm::from_buffer(buf)? as *const _) })
}
OpcodeM0ToM4::McpsDataCnf => {
MacEvent::McpsDataCnf(unsafe { &*(DataConfirm::from_buffer(buf)? as *const _) })
}
OpcodeM0ToM4::McpsPurgeCnf => {
MacEvent::McpsPurgeCnf(unsafe { &*(PurgeConfirm::from_buffer(buf)? as *const _) })
}
OpcodeM0ToM4::MlmeAssociateInd => {
MacEvent::MlmeAssociateInd(unsafe { &*(AssociateIndication::from_buffer(buf)? as *const _) })
}
OpcodeM0ToM4::MlmeDisassociateInd => {
MacEvent::MlmeDisassociateInd(unsafe { &*(DisassociateIndication::from_buffer(buf)? as *const _) })
}
OpcodeM0ToM4::MlmeBeaconNotifyInd => {
MacEvent::MlmeBeaconNotifyInd(unsafe { &*(BeaconNotifyIndication::from_buffer(buf)? as *const _) })
}
OpcodeM0ToM4::MlmeCommStatusInd => {
MacEvent::MlmeCommStatusInd(unsafe { &*(CommStatusIndication::from_buffer(buf)? as *const _) })
}
OpcodeM0ToM4::MlmeGtsInd => {
MacEvent::MlmeGtsInd(unsafe { &*(GtsIndication::from_buffer(buf)? as *const _) })
}
OpcodeM0ToM4::MlmeOrphanInd => {
MacEvent::MlmeOrphanInd(unsafe { &*(OrphanIndication::from_buffer(buf)? as *const _) })
}
OpcodeM0ToM4::MlmeSyncLossInd => {
MacEvent::MlmeSyncLossInd(unsafe { &*(SyncLossIndication::from_buffer(buf)? as *const _) })
}
OpcodeM0ToM4::MlmeDpsInd => {
MacEvent::MlmeDpsInd(unsafe { &*(DpsIndication::from_buffer(buf)? as *const _) })
}
OpcodeM0ToM4::McpsDataInd => {
MacEvent::McpsDataInd(unsafe { &*(DataIndication::from_buffer(buf)? as *const _) })
}
OpcodeM0ToM4::MlmePollInd => {
MacEvent::MlmePollInd(unsafe { &*(PollIndication::from_buffer(buf)? as *const _) })
}
};
// Forget the event box so that drop isn't called
// We want to handle the lifetime ourselves
mem::forget(event_box);
Ok(mac_event)
}
}
unsafe impl<'a> Send for MacEvent<'a> {}
impl<'a> Drop for MacEvent<'a> {
fn drop(&mut self) {
unsafe { mac::Mac::drop_event_packet(ptr::null_mut()) };
}
}