use enumset::{EnumSet, EnumSetType};
use esp_config::esp_config_int;
use esp_sync::NonReentrantMutex;
use num_derive::FromPrimitive;
use super::Ssid;
static WIFI_EVENT_ENABLE_MASK: NonReentrantMutex<EnumSet<WifiEvent>> =
NonReentrantMutex::new(enumset::enum_set!());
pub(crate) static EVENT_CHANNEL: embassy_sync::pubsub::PubSubChannel<
esp_sync::RawMutex,
EventInfo,
{ esp_config_int!(usize, "ESP_RADIO_CONFIG_EVENT_CHANNEL_CAPACITY") },
{ esp_config_int!(usize, "ESP_RADIO_CONFIG_EVENT_CHANNEL_SUBSCRIBERS") },
1,
> = embassy_sync::pubsub::PubSubChannel::new();
#[derive(Debug, Hash, FromPrimitive, EnumSetType)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
#[repr(i32)]
#[instability::unstable]
pub enum WifiEvent {
WifiReady = 0,
ScanDone,
StationStart,
StationStop,
StationConnected,
StationDisconnected,
StationAuthenticationModeChange,
StationWifiProtectedStatusEnrolleeSuccess,
StationWifiProtectedStatusEnrolleeFailed,
StationWifiProtectedStatusEnrolleeTimeout,
StationWifiProtectedStatusEnrolleePin,
StationWifiProtectedStatusEnrolleePushButtonConfigurationOverlap,
AccessPointStart,
AccessPointStop,
AccessPointStationConnected,
AccessPointStationDisconnected,
AccessPointProbeRequestReceived,
FineTimingMeasurementReport,
StationBasicServiceSetReceivedSignalStrengthIndicatorLow,
ActionTransmissionStatus,
RemainOnChannelDone,
StationBeaconTimeout,
ConnectionlessModuleWakeIntervalStart,
AccessPointWifiProtectedStatusRegistrarSuccess,
AccessPointWifiProtectedStatusRegistrarFailed,
AccessPointWifiProtectedStatusRegistrarTimeout,
AccessPointWifiProtectedStatusRegistrarPin,
AccessPointWifiProtectedStatusRegistrarPushButtonConfigurationOverlap,
IndividualTargetWakeTimeSetup,
IndividualTargetWakeTimeTeardown,
IndividualTargetWakeTimeProbe,
IndividualTargetWakeTimeSuspend,
TargetWakeTimeWakeup,
BroadcastTargetWakeTimeSetup,
BroadcastTargetWakeTimeTeardown,
NeighborAwarenessNetworkingStarted,
NeighborAwarenessNetworkingStopped,
NeighborAwarenessNetworkingServiceMatch,
NeighborAwarenessNetworkingReplied,
NeighborAwarenessNetworkingReceive,
NeighborDiscoveryProtocolIndication,
NeighborDiscoveryProtocolConfirmation,
NeighborDiscoveryProtocolTerminated,
HomeChannelChange,
StationNeighborRep,
}
trait Event {
unsafe fn from_raw_event_data(ptr: *mut crate::sys::c_types::c_void) -> Self;
}
macro_rules! impl_wifi_event {
($newtype:ident) => {
#[derive(Copy, Clone)]
#[instability::unstable]
pub struct $newtype;
impl Event for $newtype {
unsafe fn from_raw_event_data(_: *mut crate::sys::c_types::c_void) -> Self {
Self
}
}
};
($newtype:ident, $data:ident) => {
use crate::sys::include::$data;
#[derive(Copy, Clone)]
#[instability::unstable]
pub struct $newtype<'a>(&'a $data);
impl Event for $newtype<'_> {
unsafe fn from_raw_event_data(ptr: *mut crate::sys::c_types::c_void) -> Self {
Self(unsafe { &*ptr.cast() })
}
}
};
}
impl_wifi_event!(WifiReady);
impl_wifi_event!(ScanDone, wifi_event_sta_scan_done_t);
impl_wifi_event!(StationStart);
impl_wifi_event!(StationStop);
impl_wifi_event!(StationConnected, wifi_event_sta_connected_t);
impl_wifi_event!(StationDisconnected, wifi_event_sta_disconnected_t);
impl_wifi_event!(
StationAuthenticationModeChange,
wifi_event_sta_authmode_change_t
);
impl_wifi_event!(
StationWifiProtectedStatusEnrolleeSuccess,
wifi_event_sta_wps_er_success_t
);
impl_wifi_event!(StationWifiProtectedStatusEnrolleeFailed);
impl_wifi_event!(StationWifiProtectedStatusEnrolleeTimeout);
impl_wifi_event!(
StationWifiProtectedStatusEnrolleePin,
wifi_event_sta_wps_er_pin_t
);
impl_wifi_event!(StationWifiProtectedStatusEnrolleePushButtonConfigurationOverlap);
impl_wifi_event!(AccessPointStart);
impl_wifi_event!(AccessPointStop);
impl_wifi_event!(AccessPointStationConnected, wifi_event_ap_staconnected_t);
impl_wifi_event!(
AccessPointStationDisconnected,
wifi_event_ap_stadisconnected_t
);
impl_wifi_event!(
AccessPointProbeRequestReceived,
wifi_event_ap_probe_req_rx_t
);
impl_wifi_event!(FineTimingMeasurementReport, wifi_event_ftm_report_t);
impl_wifi_event!(
StationBasicServiceSetReceivedSignalStrengthIndicatorLow,
wifi_event_bss_rssi_low_t
);
impl_wifi_event!(ActionTransmissionStatus, wifi_event_action_tx_status_t);
impl_wifi_event!(RemainOnChannelDone, wifi_event_roc_done_t);
impl_wifi_event!(StationBeaconTimeout);
impl_wifi_event!(ConnectionlessModuleWakeIntervalStart);
impl_wifi_event!(
AccessPointWifiProtectedStatusRegistrarSuccess,
wifi_event_ap_wps_rg_success_t
);
impl_wifi_event!(
AccessPointWifiProtectedStatusRegistrarFailed,
wifi_event_ap_wps_rg_fail_reason_t
);
impl_wifi_event!(AccessPointWifiProtectedStatusRegistrarTimeout);
impl_wifi_event!(
AccessPointWifiProtectedStatusRegistrarPin,
wifi_event_ap_wps_rg_pin_t
);
impl_wifi_event!(AccessPointWifiProtectedStatusRegistrarPushButtonConfigurationOverlap);
impl_wifi_event!(IndividualTargetWakeTimeSetup);
impl_wifi_event!(IndividualTargetWakeTimeTeardown);
impl_wifi_event!(IndividualTargetWakeTimeProbe);
impl_wifi_event!(IndividualTargetWakeTimeSuspend);
impl_wifi_event!(TargetWakeTimeWakeup);
impl_wifi_event!(BroadcastTargetWakeTimeSetup);
impl_wifi_event!(BroadcastTargetWakeTimeTeardown);
impl_wifi_event!(NeighborAwarenessNetworkingStarted);
impl_wifi_event!(NeighborAwarenessNetworkingStopped);
impl_wifi_event!(
NeighborAwarenessNetworkingServiceMatch,
wifi_event_nan_svc_match_t
);
impl_wifi_event!(NeighborAwarenessNetworkingReplied, wifi_event_nan_replied_t);
impl_wifi_event!(NeighborAwarenessNetworkingReceive, wifi_event_nan_receive_t);
impl_wifi_event!(
NeighborDiscoveryProtocolIndication,
wifi_event_ndp_indication_t
);
impl_wifi_event!(
NeighborDiscoveryProtocolConfirmation,
wifi_event_ndp_confirm_t
);
impl_wifi_event!(
NeighborDiscoveryProtocolTerminated,
wifi_event_ndp_terminated_t
);
impl_wifi_event!(HomeChannelChange, wifi_event_home_channel_change_t);
impl_wifi_event!(StationNeighborRep, wifi_event_neighbor_report_t);
impl_wifi_event!(
AccessPointCredential,
wifi_event_sta_wps_er_success_t__bindgen_ty_1
);
impl_wifi_event!(FineTimingMeasurementReportEntry, wifi_ftm_report_entry_t);
impl AccessPointStationConnected<'_> {
pub fn mac(&self) -> &[u8] {
&self.0.mac
}
pub fn aid(&self) -> u8 {
self.0.aid
}
pub fn is_mesh_child(&self) -> bool {
self.0.is_mesh_child
}
}
impl AccessPointStationDisconnected<'_> {
pub fn mac(&self) -> &[u8] {
&self.0.mac
}
pub fn reason(&self) -> u16 {
self.0.reason
}
pub fn aid(&self) -> u8 {
self.0.aid
}
pub fn is_mesh_child(&self) -> bool {
self.0.is_mesh_child
}
}
impl ScanDone<'_> {
pub fn status(&self) -> u32 {
self.0.status
}
pub fn number(&self) -> u8 {
self.0.number
}
pub fn id(&self) -> u8 {
self.0.scan_id
}
}
impl StationConnected<'_> {
pub fn ssid(&self) -> &[u8] {
&self.0.ssid
}
pub fn ssid_len(&self) -> u8 {
self.0.ssid_len
}
pub fn bssid(&self) -> &[u8] {
&self.0.bssid
}
pub fn channel(&self) -> u8 {
self.0.channel
}
pub fn authmode(&self) -> u32 {
self.0.authmode
}
pub fn aid(&self) -> u16 {
self.0.aid
}
}
impl StationDisconnected<'_> {
pub fn ssid(&self) -> &[u8] {
&self.0.ssid
}
pub fn ssid_len(&self) -> u8 {
self.0.ssid_len
}
pub fn bssid(&self) -> &[u8] {
&self.0.bssid
}
pub fn reason(&self) -> u8 {
self.0.reason
}
pub fn rssi(&self) -> i8 {
self.0.rssi
}
}
impl AccessPointCredential<'_> {
pub fn ssid(&self) -> &[u8] {
&self.0.ssid
}
pub fn passphrase(&self) -> &[u8] {
&self.0.passphrase
}
}
impl StationAuthenticationModeChange<'_> {
pub fn old_mode(&self) -> u32 {
self.0.old_mode
}
pub fn new_mode(&self) -> u32 {
self.0.new_mode
}
}
impl StationWifiProtectedStatusEnrolleeSuccess<'_> {
pub fn access_point_cred_cnt(&self) -> u8 {
self.0.ap_cred_cnt
}
pub fn access_point_cred(&self) -> &[AccessPointCredential<'_>] {
let array_ref: &[AccessPointCredential<'_>; 3] =
unsafe { &*(&self.0.ap_cred as *const _ as *const [AccessPointCredential<'_>; 3]) };
&array_ref[..]
}
}
impl StationWifiProtectedStatusEnrolleePin<'_> {
pub fn pin(&self) -> &[u8] {
&self.0.pin_code
}
}
impl FineTimingMeasurementReportEntry<'_> {
pub fn dialog_token(&self) -> u8 {
self.0.dlog_token
}
pub fn rssi(&self) -> i8 {
self.0.rssi
}
pub fn rtt(&self) -> u32 {
self.0.rtt
}
pub fn t1(&self) -> u64 {
self.0.t1
}
pub fn t2(&self) -> u64 {
self.0.t2
}
pub fn t3(&self) -> u64 {
self.0.t3
}
pub fn t4(&self) -> u64 {
self.0.t4
}
}
impl FineTimingMeasurementReport<'_> {
pub fn peer_mac(&self) -> &[u8] {
&self.0.peer_mac
}
pub fn status(&self) -> u32 {
self.0.status
}
pub fn rtt_raw(&self) -> u32 {
self.0.rtt_raw
}
pub fn rtt_est(&self) -> u32 {
self.0.rtt_est
}
pub fn dist_est(&self) -> u32 {
self.0.dist_est
}
pub fn report_num_entries(&self) -> u8 {
self.0.ftm_report_num_entries
}
pub fn entries(&self) -> impl Iterator<Item = FineTimingMeasurementReportEntry<'_>> + '_ {
let ptr = self.0.ftm_report_data;
let len = self.0.ftm_report_num_entries as usize;
let entries_slice = if ptr.is_null() || len == 0 {
&[]
} else {
unsafe { core::slice::from_raw_parts(ptr, len) }
};
entries_slice.iter().map(FineTimingMeasurementReportEntry)
}
}
impl AccessPointProbeRequestReceived<'_> {
pub fn rssi(&self) -> i32 {
self.0.rssi
}
pub fn mac(&self) -> &[u8] {
&self.0.mac
}
}
impl StationBasicServiceSetReceivedSignalStrengthIndicatorLow<'_> {
pub fn rssi(&self) -> i32 {
self.0.rssi
}
}
impl ActionTransmissionStatus<'_> {
pub fn ifx(&self) -> u32 {
self.0.ifx
}
pub fn context(&self) -> u32 {
self.0.context
}
pub fn op_id(&self) -> u8 {
self.0.op_id
}
pub fn channel(&self) -> u8 {
self.0.channel
}
pub fn status(&self) -> u32 {
self.0.status
}
}
impl RemainOnChannelDone<'_> {
pub fn context(&self) -> u32 {
self.0.context
}
pub fn status(&self) -> u32 {
self.0.status
}
pub fn op_id(&self) -> u8 {
self.0.op_id
}
pub fn channel(&self) -> u8 {
self.0.channel
}
}
impl AccessPointWifiProtectedStatusRegistrarSuccess<'_> {
pub fn peer_mac(&self) -> &[u8] {
&self.0.peer_macaddr
}
}
impl AccessPointWifiProtectedStatusRegistrarFailed<'_> {
pub fn reason(&self) -> u32 {
self.0.reason
}
pub fn peer_macaddr(&self) -> &[u8; 6] {
&self.0.peer_macaddr
}
}
impl AccessPointWifiProtectedStatusRegistrarPin<'_> {
pub fn pin_code(&self) -> &[u8] {
&self.0.pin_code
}
}
impl NeighborAwarenessNetworkingServiceMatch<'_> {
pub fn subscribe_id(&self) -> u8 {
self.0.subscribe_id
}
pub fn publish_id(&self) -> u8 {
self.0.publish_id
}
pub fn pub_if_mac(&self) -> &[u8] {
&self.0.pub_if_mac
}
pub fn update_pub_id(&self) -> bool {
self.0.update_pub_id
}
}
impl NeighborAwarenessNetworkingReplied<'_> {
pub fn subscribe_id(&self) -> u8 {
self.0.subscribe_id
}
pub fn publish_id(&self) -> u8 {
self.0.publish_id
}
pub fn sub_if_mac(&self) -> &[u8] {
&self.0.sub_if_mac
}
}
impl NeighborAwarenessNetworkingReceive<'_> {
pub fn inst_id(&self) -> u8 {
self.0.inst_id
}
pub fn peer_inst_id(&self) -> u8 {
self.0.peer_inst_id
}
pub fn peer_if_mac(&self) -> &[u8; 6] {
&self.0.peer_if_mac
}
pub fn peer_svc_info(&self) -> &[u8; 64] {
&self.0.peer_svc_info
}
}
impl NeighborDiscoveryProtocolIndication<'_> {
pub fn publish_id(&self) -> u8 {
self.0.publish_id
}
pub fn ndp_id(&self) -> u8 {
self.0.ndp_id
}
pub fn peer_nmi(&self) -> &[u8; 6] {
&self.0.peer_nmi
}
pub fn peer_ndi(&self) -> &[u8; 6] {
&self.0.peer_ndi
}
pub fn svc_info(&self) -> &[u8; 64] {
&self.0.svc_info
}
}
impl NeighborDiscoveryProtocolConfirmation<'_> {
pub fn status(&self) -> u8 {
self.0.status
}
pub fn id(&self) -> u8 {
self.0.ndp_id
}
pub fn peer_nmi(&self) -> &[u8; 6] {
&self.0.peer_nmi
}
pub fn peer_ndi(&self) -> &[u8; 6] {
&self.0.peer_ndi
}
pub fn own_ndi(&self) -> &[u8; 6] {
&self.0.own_ndi
}
pub fn svc_info(&self) -> &[u8; 64] {
&self.0.svc_info
}
}
impl NeighborDiscoveryProtocolTerminated<'_> {
pub fn reason(&self) -> u8 {
self.0.reason
}
pub fn id(&self) -> u8 {
self.0.ndp_id
}
pub fn init_ndi(&self) -> &[u8; 6] {
&self.0.init_ndi
}
}
impl HomeChannelChange<'_> {
pub fn old_chan(&self) -> u8 {
self.0.old_chan
}
pub fn old_snd(&self) -> u32 {
self.0.old_snd
}
pub fn new_chan(&self) -> u8 {
self.0.new_chan
}
pub fn new_snd(&self) -> u32 {
self.0.new_snd
}
}
impl StationNeighborRep<'_> {
pub fn report(&self) -> &[u8] {
&self.0.report[..self.0.report_len as usize]
}
pub fn report_len(&self) -> u16 {
self.0.report_len
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[instability::unstable]
pub struct FineTimingMeasurementReportInfo {
pub dlog_token: u8,
pub rssi: i8,
pub rtt: u32,
pub t1: u64,
pub t2: u64,
pub t3: u64,
pub t4: u64,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[instability::unstable]
pub struct CredentialsInfo {
pub ssid: Ssid,
pub passphrase: [u8; 64usize],
}
#[derive(Debug, Clone)]
pub struct Collection<T>(alloc::vec::Vec<T>);
impl<T> Collection<T> {
pub fn as_slice(&self) -> &[T] {
self.0.as_slice()
}
}
#[cfg(feature = "defmt")]
impl<T: defmt::Format> defmt::Format for Collection<T> {
fn format(&self, fmt: defmt::Formatter<'_>) {
self.0.iter().for_each(|v| {
defmt::write!(fmt, "{}", v);
});
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[instability::unstable]
pub enum EventInfo {
WifiReady,
ScanDone {
status: u32,
number: u8,
scan_id: u8,
},
StationStart,
StationStop,
StationConnected {
ssid: Ssid,
bssid: [u8; 6usize],
channel: u8,
authmode: u32,
aid: u16,
},
StationDisconnected {
ssid: Ssid,
bssid: [u8; 6usize],
reason: u16,
rssi: i8,
},
StationAuthenticationModeChange {
old_mode: u32,
new_mode: u32,
},
StationWifiProtectedStatusEnrolleeSuccess {
credentials: Collection<CredentialsInfo>,
},
StationWifiProtectedStatusEnrolleeFailed,
StationWifiProtectedStatusEnrolleeTimeout,
StationWifiProtectedStatusEnrolleePin {
pin_code: [u8; 8usize],
},
StationWifiProtectedStatusEnrolleePushButtonConfigurationOverlap,
AccessPointStart,
AccessPointStop,
AccessPointStationConnected {
mac: [u8; 6usize],
aid: u16,
is_mesh_child: bool,
},
AccessPointStationDisconnected {
mac: [u8; 6usize],
aid: u8,
is_mesh_child: bool,
reason: u16,
},
AccessPointProbeRequestReceived {
rssi: i8,
mac: [u8; 6usize],
},
FineTimingMeasurementReport {
peer_mac: [u8; 6usize],
status: u32,
rtt_raw: u32,
rtt_est: u32,
dist_est: u32,
entries: Collection<FineTimingMeasurementReportInfo>,
},
StationBasicServiceSetReceivedSignalStrengthIndicatorLow {
rssi: i8,
},
ActionTransmissionStatus {
ifx: u32,
context: u32,
status: u32,
op_id: u8,
channel: u8,
},
RemainOnChannelDone {
context: u32,
status: u32,
op_id: u8,
channel: u8,
},
StationBeaconTimeout,
ConnectionlessModuleWakeIntervalStart,
AccessPointWifiProtectedStatusRegistrarSuccess {
peer_macaddr: [u8; 6usize],
},
AccessPointWifiProtectedStatusRegistrarFailed {
reason: u32,
peer_macaddr: [u8; 6usize],
},
AccessPointWifiProtectedStatusRegistrarTimeout,
AccessPointWifiProtectedStatusRegistrarPin {
pin_code: [u8; 8usize],
},
AccessPointWifiProtectedStatusRegistrarPushButtonConfigurationOverlap,
IndividualTargetWakeTimeSetup,
IndividualTargetWakeTimeTeardown,
IndividualTargetWakeTimeProbe,
IndividualTargetWakeTimeSuspend,
TargetWakeTimeWakeup,
BroadcastTargetWakeTimeSetup,
BroadcastTargetWakeTimeTeardown,
HomeChannelChange,
}
impl EventInfo {
pub(crate) fn from_wifi_event_raw(
event: WifiEvent,
payload: *mut crate::sys::c_types::c_void,
) -> Option<Self> {
let enabled = WIFI_EVENT_ENABLE_MASK.with(|mask| mask.contains(event));
if !enabled {
return None;
}
match event {
WifiEvent::WifiReady => Some(EventInfo::WifiReady),
WifiEvent::ScanDone => {
let ev = unsafe { ScanDone::from_raw_event_data(payload) };
Some(EventInfo::ScanDone {
status: ev.status(),
number: ev.number(),
scan_id: ev.id(),
})
}
WifiEvent::StationStart => Some(EventInfo::StationStart),
WifiEvent::StationStop => Some(EventInfo::StationStop),
WifiEvent::StationConnected => {
let ev = unsafe { StationConnected::from_raw_event_data(payload) };
Some(EventInfo::StationConnected {
ssid: Ssid::from_raw(ev.ssid(), ev.ssid_len()),
bssid: ev.bssid().try_into().unwrap(),
channel: ev.channel(),
authmode: ev.authmode(),
aid: ev.aid(),
})
}
WifiEvent::StationDisconnected => {
let ev = unsafe { StationDisconnected::from_raw_event_data(payload) };
Some(EventInfo::StationDisconnected {
ssid: Ssid::from_raw(ev.ssid(), ev.ssid_len()),
bssid: ev.bssid().try_into().unwrap(),
reason: ev.reason() as u16,
rssi: ev.rssi(),
})
}
WifiEvent::AccessPointStart => Some(EventInfo::AccessPointStart),
WifiEvent::AccessPointStop => Some(EventInfo::AccessPointStop),
WifiEvent::AccessPointStationConnected => {
let ev = unsafe { AccessPointStationConnected::from_raw_event_data(payload) };
Some(EventInfo::AccessPointStationConnected {
mac: ev.mac().try_into().unwrap(),
aid: ev.aid() as u16,
is_mesh_child: ev.is_mesh_child(),
})
}
WifiEvent::AccessPointStationDisconnected => {
let ev = unsafe { AccessPointStationDisconnected::from_raw_event_data(payload) };
Some(EventInfo::AccessPointStationDisconnected {
mac: ev.mac().try_into().unwrap(),
aid: ev.aid(),
is_mesh_child: ev.is_mesh_child(),
reason: ev.reason(),
})
}
WifiEvent::StationAuthenticationModeChange => {
let ev = unsafe { StationAuthenticationModeChange::from_raw_event_data(payload) };
Some(EventInfo::StationAuthenticationModeChange {
old_mode: ev.old_mode(),
new_mode: ev.new_mode(),
})
}
WifiEvent::StationWifiProtectedStatusEnrolleeSuccess => {
let ev = unsafe {
StationWifiProtectedStatusEnrolleeSuccess::from_raw_event_data(payload)
};
Some(EventInfo::StationWifiProtectedStatusEnrolleeSuccess {
credentials: Collection(ev
.access_point_cred()[..ev.access_point_cred_cnt() as usize].iter()
.map(|cred| CredentialsInfo {
ssid: cred.ssid().into(),
passphrase: cred.passphrase().try_into().unwrap(),
})
.collect()),
})
}
WifiEvent::StationWifiProtectedStatusEnrolleeFailed => {
Some(EventInfo::StationWifiProtectedStatusEnrolleeFailed)
}
WifiEvent::StationWifiProtectedStatusEnrolleeTimeout => {
Some(EventInfo::StationWifiProtectedStatusEnrolleeTimeout)
}
WifiEvent::StationWifiProtectedStatusEnrolleePin => {
let ev =
unsafe { StationWifiProtectedStatusEnrolleePin::from_raw_event_data(payload) };
Some(EventInfo::StationWifiProtectedStatusEnrolleePin {
pin_code: ev.pin().try_into().unwrap_or_default(),
})
}
WifiEvent::StationWifiProtectedStatusEnrolleePushButtonConfigurationOverlap => {
Some(EventInfo::StationWifiProtectedStatusEnrolleePushButtonConfigurationOverlap)
}
WifiEvent::AccessPointProbeRequestReceived => {
let ev = unsafe { AccessPointProbeRequestReceived::from_raw_event_data(payload) };
Some(EventInfo::AccessPointProbeRequestReceived {
rssi: ev.rssi() as i8,
mac: ev.mac().try_into().unwrap_or_default(),
})
}
WifiEvent::FineTimingMeasurementReport => {
let ev = unsafe { FineTimingMeasurementReport::from_raw_event_data(payload) };
Some(EventInfo::FineTimingMeasurementReport {
peer_mac: ev.peer_mac().try_into().unwrap_or_default(),
status: ev.status(),
rtt_raw: ev.rtt_raw(),
rtt_est: ev.rtt_est(),
dist_est: ev.dist_est(),
entries: Collection(ev
.entries()
.map(|entry| FineTimingMeasurementReportInfo {
dlog_token: entry.dialog_token(),
rssi: entry.rssi(),
rtt: entry.rtt(),
t1: entry.t1(),
t2: entry.t2(),
t3: entry.t3(),
t4: entry.t4(),
})
.collect()),
})
}
WifiEvent::StationBasicServiceSetReceivedSignalStrengthIndicatorLow => {
let ev = unsafe {
StationBasicServiceSetReceivedSignalStrengthIndicatorLow::from_raw_event_data(
payload,
)
};
Some(
EventInfo::StationBasicServiceSetReceivedSignalStrengthIndicatorLow {
rssi: ev.rssi() as i8,
},
)
}
WifiEvent::ActionTransmissionStatus => {
let ev = unsafe { ActionTransmissionStatus::from_raw_event_data(payload) };
Some(EventInfo::ActionTransmissionStatus {
ifx: ev.ifx(),
context: ev.context(),
status: ev.status(),
op_id: ev.op_id(),
channel: ev.channel(),
})
}
WifiEvent::RemainOnChannelDone => {
let ev = unsafe { RemainOnChannelDone::from_raw_event_data(payload) };
Some(EventInfo::RemainOnChannelDone {
context: ev.context(),
status: ev.status(),
op_id: ev.op_id(),
channel: ev.channel(),
})
}
WifiEvent::StationBeaconTimeout => Some(EventInfo::StationBeaconTimeout),
WifiEvent::ConnectionlessModuleWakeIntervalStart => {
Some(EventInfo::ConnectionlessModuleWakeIntervalStart)
}
WifiEvent::AccessPointWifiProtectedStatusRegistrarSuccess => {
let ev = unsafe {
AccessPointWifiProtectedStatusRegistrarSuccess::from_raw_event_data(payload)
};
Some(EventInfo::AccessPointWifiProtectedStatusRegistrarSuccess {
peer_macaddr: ev.peer_mac().try_into().unwrap_or_default(),
})
}
WifiEvent::AccessPointWifiProtectedStatusRegistrarFailed => {
let ev = unsafe {
AccessPointWifiProtectedStatusRegistrarFailed::from_raw_event_data(payload)
};
Some(EventInfo::AccessPointWifiProtectedStatusRegistrarFailed {
reason: ev.reason(),
peer_macaddr: *ev.peer_macaddr(),
})
}
WifiEvent::AccessPointWifiProtectedStatusRegistrarTimeout => {
Some(EventInfo::AccessPointWifiProtectedStatusRegistrarTimeout)
}
WifiEvent::AccessPointWifiProtectedStatusRegistrarPin => {
let ev = unsafe {
AccessPointWifiProtectedStatusRegistrarPin::from_raw_event_data(payload)
};
Some(EventInfo::AccessPointWifiProtectedStatusRegistrarPin {
pin_code: ev.pin_code().try_into().unwrap_or_default(),
})
}
WifiEvent::AccessPointWifiProtectedStatusRegistrarPushButtonConfigurationOverlap => {
Some(EventInfo::AccessPointWifiProtectedStatusRegistrarPushButtonConfigurationOverlap)
}
WifiEvent::IndividualTargetWakeTimeSetup => {
Some(EventInfo::IndividualTargetWakeTimeSetup)
}
WifiEvent::IndividualTargetWakeTimeTeardown => {
Some(EventInfo::IndividualTargetWakeTimeTeardown)
}
WifiEvent::IndividualTargetWakeTimeProbe => {
Some(EventInfo::IndividualTargetWakeTimeProbe)
}
WifiEvent::IndividualTargetWakeTimeSuspend => {
Some(EventInfo::IndividualTargetWakeTimeSuspend)
}
WifiEvent::TargetWakeTimeWakeup => {
Some(EventInfo::TargetWakeTimeWakeup)
}
WifiEvent::BroadcastTargetWakeTimeSetup => {
Some(EventInfo::BroadcastTargetWakeTimeSetup)
}
WifiEvent::BroadcastTargetWakeTimeTeardown => {
Some(EventInfo::BroadcastTargetWakeTimeTeardown)
}
WifiEvent::HomeChannelChange => {
Some(EventInfo::HomeChannelChange)
}
_ => None,
}
}
}
#[instability::unstable]
pub fn enable_wifi_events(events: EnumSet<WifiEvent>) {
WIFI_EVENT_ENABLE_MASK.with(|mask| *mask |= events);
}
#[instability::unstable]
pub fn disable_wifi_events(events: EnumSet<WifiEvent>) {
WIFI_EVENT_ENABLE_MASK.with(|mask| *mask &= !events);
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[instability::unstable]
pub enum MessageResult {
Lagged(u64),
Message(EventInfo),
}
#[instability::unstable]
pub struct EventSubscriber<'a> {
inner: embassy_sync::pubsub::Subscriber<
'a,
esp_sync::RawMutex,
EventInfo,
{ esp_config_int!(usize, "ESP_RADIO_CONFIG_EVENT_CHANNEL_CAPACITY") },
{ esp_config_int!(usize, "ESP_RADIO_CONFIG_EVENT_CHANNEL_SUBSCRIBERS") },
1,
>,
}
impl<'a> EventSubscriber<'a> {
pub(crate) fn new(
subscriber: embassy_sync::pubsub::Subscriber<
'a,
esp_sync::RawMutex,
EventInfo,
{ esp_config_int!(usize, "ESP_RADIO_CONFIG_EVENT_CHANNEL_CAPACITY") },
{ esp_config_int!(usize, "ESP_RADIO_CONFIG_EVENT_CHANNEL_SUBSCRIBERS") },
1,
>,
) -> Self {
Self { inner: subscriber }
}
#[instability::unstable]
pub async fn next_event(&mut self) -> MessageResult {
match self.inner.next_message().await {
embassy_sync::pubsub::WaitResult::Lagged(missed) => MessageResult::Lagged(missed),
embassy_sync::pubsub::WaitResult::Message(msg) => MessageResult::Message(msg),
}
}
#[instability::unstable]
pub async fn next_event_pure(&mut self) -> EventInfo {
self.inner.next_message_pure().await
}
}