1use enumset::{EnumSet, EnumSetType};
7use esp_config::esp_config_int;
8use esp_sync::NonReentrantMutex;
9use num_derive::FromPrimitive;
10
11use super::Ssid;
12
13static WIFI_EVENT_ENABLE_MASK: NonReentrantMutex<EnumSet<WifiEvent>> =
14 NonReentrantMutex::new(enumset::enum_set!());
15
16pub(crate) static EVENT_CHANNEL: embassy_sync::pubsub::PubSubChannel<
17 esp_sync::RawMutex,
18 EventInfo,
19 { esp_config_int!(usize, "ESP_RADIO_CONFIG_EVENT_CHANNEL_CAPACITY") },
20 { esp_config_int!(usize, "ESP_RADIO_CONFIG_EVENT_CHANNEL_SUBSCRIBERS") },
21 1,
22> = embassy_sync::pubsub::PubSubChannel::new();
23
24#[derive(Debug, Hash, FromPrimitive, EnumSetType)]
26#[cfg_attr(feature = "defmt", derive(defmt::Format))]
27#[non_exhaustive]
28#[repr(i32)]
29#[instability::unstable]
30pub enum WifiEvent {
31 WifiReady = 0,
33 ScanDone,
35 StationStart,
37 StationStop,
39 StationConnected,
41 StationDisconnected,
43 StationAuthenticationModeChange,
45
46 StationWifiProtectedStatusEnrolleeSuccess,
48 StationWifiProtectedStatusEnrolleeFailed,
50 StationWifiProtectedStatusEnrolleeTimeout,
52 StationWifiProtectedStatusEnrolleePin,
54 StationWifiProtectedStatusEnrolleePushButtonConfigurationOverlap,
56
57 AccessPointStart,
59 AccessPointStop,
61 AccessPointStationConnected,
63 AccessPointStationDisconnected,
65 AccessPointProbeRequestReceived,
67
68 FineTimingMeasurementReport,
70
71 StationBasicServiceSetReceivedSignalStrengthIndicatorLow,
73 ActionTransmissionStatus,
75 RemainOnChannelDone,
77
78 StationBeaconTimeout,
80
81 ConnectionlessModuleWakeIntervalStart,
83
84 AccessPointWifiProtectedStatusRegistrarSuccess,
86 AccessPointWifiProtectedStatusRegistrarFailed,
88 AccessPointWifiProtectedStatusRegistrarTimeout,
90 AccessPointWifiProtectedStatusRegistrarPin,
92 AccessPointWifiProtectedStatusRegistrarPushButtonConfigurationOverlap,
94
95 IndividualTargetWakeTimeSetup,
97 IndividualTargetWakeTimeTeardown,
99 IndividualTargetWakeTimeProbe,
101 IndividualTargetWakeTimeSuspend,
103 TargetWakeTimeWakeup,
105 BroadcastTargetWakeTimeSetup,
107 BroadcastTargetWakeTimeTeardown,
109
110 NeighborAwarenessNetworkingStarted,
112 NeighborAwarenessNetworkingStopped,
114 NeighborAwarenessNetworkingServiceMatch,
116 NeighborAwarenessNetworkingReplied,
118 NeighborAwarenessNetworkingReceive,
120 NeighborDiscoveryProtocolIndication,
123 NeighborDiscoveryProtocolConfirmation,
125 NeighborDiscoveryProtocolTerminated,
127 HomeChannelChange,
129
130 StationNeighborRep,
132}
133
134trait Event {
135 unsafe fn from_raw_event_data(ptr: *mut crate::sys::c_types::c_void) -> Self;
138}
139
140macro_rules! impl_wifi_event {
141 ($newtype:ident) => {
143 #[derive(Copy, Clone)]
145 #[instability::unstable]
146 pub struct $newtype;
147
148 impl Event for $newtype {
149 unsafe fn from_raw_event_data(_: *mut crate::sys::c_types::c_void) -> Self {
150 Self
151 }
152 }
153 };
154
155 ($newtype:ident, $data:ident) => {
156 use crate::sys::include::$data;
157 #[derive(Copy, Clone)]
159 #[instability::unstable]
160 pub struct $newtype<'a>(&'a $data);
161
162 impl Event for $newtype<'_> {
163 unsafe fn from_raw_event_data(ptr: *mut crate::sys::c_types::c_void) -> Self {
164 Self(unsafe { &*ptr.cast() })
165 }
166 }
167 };
168}
169
170impl_wifi_event!(WifiReady);
171impl_wifi_event!(ScanDone, wifi_event_sta_scan_done_t);
172impl_wifi_event!(StationStart);
173impl_wifi_event!(StationStop);
174impl_wifi_event!(StationConnected, wifi_event_sta_connected_t);
175impl_wifi_event!(StationDisconnected, wifi_event_sta_disconnected_t);
176impl_wifi_event!(
177 StationAuthenticationModeChange,
178 wifi_event_sta_authmode_change_t
179);
180impl_wifi_event!(
181 StationWifiProtectedStatusEnrolleeSuccess,
182 wifi_event_sta_wps_er_success_t
183);
184impl_wifi_event!(StationWifiProtectedStatusEnrolleeFailed);
185impl_wifi_event!(StationWifiProtectedStatusEnrolleeTimeout);
186impl_wifi_event!(
187 StationWifiProtectedStatusEnrolleePin,
188 wifi_event_sta_wps_er_pin_t
189);
190impl_wifi_event!(StationWifiProtectedStatusEnrolleePushButtonConfigurationOverlap);
191impl_wifi_event!(AccessPointStart);
192impl_wifi_event!(AccessPointStop);
193impl_wifi_event!(AccessPointStationConnected, wifi_event_ap_staconnected_t);
194impl_wifi_event!(
195 AccessPointStationDisconnected,
196 wifi_event_ap_stadisconnected_t
197);
198impl_wifi_event!(
199 AccessPointProbeRequestReceived,
200 wifi_event_ap_probe_req_rx_t
201);
202impl_wifi_event!(FineTimingMeasurementReport, wifi_event_ftm_report_t);
203impl_wifi_event!(
204 StationBasicServiceSetReceivedSignalStrengthIndicatorLow,
205 wifi_event_bss_rssi_low_t
206);
207impl_wifi_event!(ActionTransmissionStatus, wifi_event_action_tx_status_t);
208impl_wifi_event!(RemainOnChannelDone, wifi_event_roc_done_t);
209impl_wifi_event!(StationBeaconTimeout);
210impl_wifi_event!(ConnectionlessModuleWakeIntervalStart);
211impl_wifi_event!(
212 AccessPointWifiProtectedStatusRegistrarSuccess,
213 wifi_event_ap_wps_rg_success_t
214);
215impl_wifi_event!(
216 AccessPointWifiProtectedStatusRegistrarFailed,
217 wifi_event_ap_wps_rg_fail_reason_t
218);
219impl_wifi_event!(AccessPointWifiProtectedStatusRegistrarTimeout);
220impl_wifi_event!(
221 AccessPointWifiProtectedStatusRegistrarPin,
222 wifi_event_ap_wps_rg_pin_t
223);
224impl_wifi_event!(AccessPointWifiProtectedStatusRegistrarPushButtonConfigurationOverlap);
225impl_wifi_event!(IndividualTargetWakeTimeSetup);
226impl_wifi_event!(IndividualTargetWakeTimeTeardown);
227impl_wifi_event!(IndividualTargetWakeTimeProbe);
228impl_wifi_event!(IndividualTargetWakeTimeSuspend);
229impl_wifi_event!(TargetWakeTimeWakeup);
230impl_wifi_event!(BroadcastTargetWakeTimeSetup);
231impl_wifi_event!(BroadcastTargetWakeTimeTeardown);
232impl_wifi_event!(NeighborAwarenessNetworkingStarted);
233impl_wifi_event!(NeighborAwarenessNetworkingStopped);
234impl_wifi_event!(
235 NeighborAwarenessNetworkingServiceMatch,
236 wifi_event_nan_svc_match_t
237);
238impl_wifi_event!(NeighborAwarenessNetworkingReplied, wifi_event_nan_replied_t);
239impl_wifi_event!(NeighborAwarenessNetworkingReceive, wifi_event_nan_receive_t);
240impl_wifi_event!(
241 NeighborDiscoveryProtocolIndication,
242 wifi_event_ndp_indication_t
243);
244impl_wifi_event!(
245 NeighborDiscoveryProtocolConfirmation,
246 wifi_event_ndp_confirm_t
247);
248impl_wifi_event!(
249 NeighborDiscoveryProtocolTerminated,
250 wifi_event_ndp_terminated_t
251);
252impl_wifi_event!(HomeChannelChange, wifi_event_home_channel_change_t);
253impl_wifi_event!(StationNeighborRep, wifi_event_neighbor_report_t);
254impl_wifi_event!(
255 AccessPointCredential,
256 wifi_event_sta_wps_er_success_t__bindgen_ty_1
257);
258impl_wifi_event!(FineTimingMeasurementReportEntry, wifi_ftm_report_entry_t);
259
260impl AccessPointStationConnected<'_> {
261 pub fn mac(&self) -> &[u8] {
263 &self.0.mac
264 }
265
266 pub fn aid(&self) -> u8 {
268 self.0.aid
269 }
270
271 pub fn is_mesh_child(&self) -> bool {
273 self.0.is_mesh_child
274 }
275}
276
277impl AccessPointStationDisconnected<'_> {
278 pub fn mac(&self) -> &[u8] {
280 &self.0.mac
281 }
282
283 pub fn reason(&self) -> u16 {
285 self.0.reason
286 }
287
288 pub fn aid(&self) -> u8 {
290 self.0.aid
291 }
292
293 pub fn is_mesh_child(&self) -> bool {
295 self.0.is_mesh_child
296 }
297}
298
299impl ScanDone<'_> {
300 pub fn status(&self) -> u32 {
302 self.0.status
303 }
304
305 pub fn number(&self) -> u8 {
307 self.0.number
308 }
309
310 pub fn id(&self) -> u8 {
312 self.0.scan_id
313 }
314}
315
316impl StationConnected<'_> {
317 pub fn ssid(&self) -> &[u8] {
319 &self.0.ssid
320 }
321
322 pub fn ssid_len(&self) -> u8 {
324 self.0.ssid_len
325 }
326
327 pub fn bssid(&self) -> &[u8] {
329 &self.0.bssid
330 }
331
332 pub fn channel(&self) -> u8 {
334 self.0.channel
335 }
336
337 pub fn authmode(&self) -> u32 {
339 self.0.authmode
340 }
341
342 pub fn aid(&self) -> u16 {
344 self.0.aid
345 }
346}
347
348impl StationDisconnected<'_> {
349 pub fn ssid(&self) -> &[u8] {
351 &self.0.ssid
352 }
353
354 pub fn ssid_len(&self) -> u8 {
356 self.0.ssid_len
357 }
358
359 pub fn bssid(&self) -> &[u8] {
361 &self.0.bssid
362 }
363
364 pub fn reason(&self) -> u8 {
366 self.0.reason
367 }
368
369 pub fn rssi(&self) -> i8 {
371 self.0.rssi
372 }
373}
374
375impl AccessPointCredential<'_> {
376 pub fn ssid(&self) -> &[u8] {
378 &self.0.ssid
379 }
380
381 pub fn passphrase(&self) -> &[u8] {
383 &self.0.passphrase
384 }
385}
386
387impl StationAuthenticationModeChange<'_> {
388 pub fn old_mode(&self) -> u32 {
390 self.0.old_mode
391 }
392
393 pub fn new_mode(&self) -> u32 {
395 self.0.new_mode
396 }
397}
398
399impl StationWifiProtectedStatusEnrolleeSuccess<'_> {
400 pub fn access_point_cred_cnt(&self) -> u8 {
402 self.0.ap_cred_cnt
403 }
404
405 pub fn access_point_cred(&self) -> &[AccessPointCredential<'_>] {
407 let array_ref: &[AccessPointCredential<'_>; 3] =
408 unsafe { &*(&self.0.ap_cred as *const _ as *const [AccessPointCredential<'_>; 3]) };
410
411 &array_ref[..]
412 }
413}
414
415impl StationWifiProtectedStatusEnrolleePin<'_> {
416 pub fn pin(&self) -> &[u8] {
418 &self.0.pin_code
419 }
420}
421
422impl FineTimingMeasurementReportEntry<'_> {
423 pub fn dialog_token(&self) -> u8 {
425 self.0.dlog_token
426 }
427
428 pub fn rssi(&self) -> i8 {
430 self.0.rssi
431 }
432
433 pub fn rtt(&self) -> u32 {
435 self.0.rtt
436 }
437
438 pub fn t1(&self) -> u64 {
440 self.0.t1
441 }
442
443 pub fn t2(&self) -> u64 {
445 self.0.t2
446 }
447
448 pub fn t3(&self) -> u64 {
450 self.0.t3
451 }
452
453 pub fn t4(&self) -> u64 {
455 self.0.t4
456 }
457}
458
459impl FineTimingMeasurementReport<'_> {
460 pub fn peer_mac(&self) -> &[u8] {
462 &self.0.peer_mac
463 }
464
465 pub fn status(&self) -> u32 {
467 self.0.status
468 }
469
470 pub fn rtt_raw(&self) -> u32 {
472 self.0.rtt_raw
473 }
474
475 pub fn rtt_est(&self) -> u32 {
477 self.0.rtt_est
478 }
479
480 pub fn dist_est(&self) -> u32 {
482 self.0.dist_est
483 }
484
485 pub fn report_num_entries(&self) -> u8 {
487 self.0.ftm_report_num_entries
488 }
489
490 pub fn entries(&self) -> impl Iterator<Item = FineTimingMeasurementReportEntry<'_>> + '_ {
492 let ptr = self.0.ftm_report_data;
493 let len = self.0.ftm_report_num_entries as usize;
494
495 let entries_slice = if ptr.is_null() || len == 0 {
497 &[]
498 } else {
499 unsafe { core::slice::from_raw_parts(ptr, len) }
502 };
503
504 entries_slice.iter().map(FineTimingMeasurementReportEntry)
505 }
506}
507
508impl AccessPointProbeRequestReceived<'_> {
509 pub fn rssi(&self) -> i32 {
511 self.0.rssi
512 }
513
514 pub fn mac(&self) -> &[u8] {
516 &self.0.mac
517 }
518}
519
520impl StationBasicServiceSetReceivedSignalStrengthIndicatorLow<'_> {
521 pub fn rssi(&self) -> i32 {
523 self.0.rssi
524 }
525}
526
527impl ActionTransmissionStatus<'_> {
528 pub fn ifx(&self) -> u32 {
530 self.0.ifx
531 }
532
533 pub fn context(&self) -> u32 {
535 self.0.context
536 }
537
538 pub fn op_id(&self) -> u8 {
540 self.0.op_id
541 }
542
543 pub fn channel(&self) -> u8 {
545 self.0.channel
546 }
547
548 pub fn status(&self) -> u32 {
550 self.0.status
551 }
552}
553
554impl RemainOnChannelDone<'_> {
555 pub fn context(&self) -> u32 {
557 self.0.context
558 }
559
560 pub fn status(&self) -> u32 {
562 self.0.status
563 }
564
565 pub fn op_id(&self) -> u8 {
567 self.0.op_id
568 }
569
570 pub fn channel(&self) -> u8 {
572 self.0.channel
573 }
574}
575
576impl AccessPointWifiProtectedStatusRegistrarSuccess<'_> {
577 pub fn peer_mac(&self) -> &[u8] {
579 &self.0.peer_macaddr
580 }
581}
582
583impl AccessPointWifiProtectedStatusRegistrarFailed<'_> {
584 pub fn reason(&self) -> u32 {
586 self.0.reason
587 }
588
589 pub fn peer_macaddr(&self) -> &[u8; 6] {
591 &self.0.peer_macaddr
592 }
593}
594
595impl AccessPointWifiProtectedStatusRegistrarPin<'_> {
596 pub fn pin_code(&self) -> &[u8] {
598 &self.0.pin_code
599 }
600}
601
602impl NeighborAwarenessNetworkingServiceMatch<'_> {
603 pub fn subscribe_id(&self) -> u8 {
605 self.0.subscribe_id
606 }
607
608 pub fn publish_id(&self) -> u8 {
610 self.0.publish_id
611 }
612
613 pub fn pub_if_mac(&self) -> &[u8] {
615 &self.0.pub_if_mac
616 }
617
618 pub fn update_pub_id(&self) -> bool {
620 self.0.update_pub_id
621 }
622}
623
624impl NeighborAwarenessNetworkingReplied<'_> {
625 pub fn subscribe_id(&self) -> u8 {
627 self.0.subscribe_id
628 }
629
630 pub fn publish_id(&self) -> u8 {
632 self.0.publish_id
633 }
634
635 pub fn sub_if_mac(&self) -> &[u8] {
637 &self.0.sub_if_mac
638 }
639}
640
641impl NeighborAwarenessNetworkingReceive<'_> {
642 pub fn inst_id(&self) -> u8 {
644 self.0.inst_id
645 }
646
647 pub fn peer_inst_id(&self) -> u8 {
649 self.0.peer_inst_id
650 }
651
652 pub fn peer_if_mac(&self) -> &[u8; 6] {
654 &self.0.peer_if_mac
655 }
656
657 pub fn peer_svc_info(&self) -> &[u8; 64] {
659 &self.0.peer_svc_info
660 }
661}
662
663impl NeighborDiscoveryProtocolIndication<'_> {
664 pub fn publish_id(&self) -> u8 {
666 self.0.publish_id
667 }
668
669 pub fn ndp_id(&self) -> u8 {
671 self.0.ndp_id
672 }
673
674 pub fn peer_nmi(&self) -> &[u8; 6] {
676 &self.0.peer_nmi
677 }
678
679 pub fn peer_ndi(&self) -> &[u8; 6] {
681 &self.0.peer_ndi
682 }
683
684 pub fn svc_info(&self) -> &[u8; 64] {
686 &self.0.svc_info
687 }
688}
689
690impl NeighborDiscoveryProtocolConfirmation<'_> {
691 pub fn status(&self) -> u8 {
693 self.0.status
694 }
695
696 pub fn id(&self) -> u8 {
698 self.0.ndp_id
699 }
700
701 pub fn peer_nmi(&self) -> &[u8; 6] {
703 &self.0.peer_nmi
704 }
705
706 pub fn peer_ndi(&self) -> &[u8; 6] {
708 &self.0.peer_ndi
709 }
710
711 pub fn own_ndi(&self) -> &[u8; 6] {
713 &self.0.own_ndi
714 }
715
716 pub fn svc_info(&self) -> &[u8; 64] {
718 &self.0.svc_info
719 }
720}
721
722impl NeighborDiscoveryProtocolTerminated<'_> {
723 pub fn reason(&self) -> u8 {
725 self.0.reason
726 }
727
728 pub fn id(&self) -> u8 {
730 self.0.ndp_id
731 }
732
733 pub fn init_ndi(&self) -> &[u8; 6] {
735 &self.0.init_ndi
736 }
737}
738
739impl HomeChannelChange<'_> {
740 pub fn old_chan(&self) -> u8 {
742 self.0.old_chan
743 }
744
745 pub fn old_snd(&self) -> u32 {
747 self.0.old_snd
748 }
749
750 pub fn new_chan(&self) -> u8 {
752 self.0.new_chan
753 }
754
755 pub fn new_snd(&self) -> u32 {
757 self.0.new_snd
758 }
759}
760
761impl StationNeighborRep<'_> {
762 pub fn report(&self) -> &[u8] {
764 &self.0.report[..self.0.report_len as usize]
765 }
766
767 pub fn report_len(&self) -> u16 {
769 self.0.report_len
770 }
771}
772
773#[derive(Debug, Clone)]
775#[cfg_attr(feature = "defmt", derive(defmt::Format))]
776#[instability::unstable]
777pub struct FineTimingMeasurementReportInfo {
778 pub dlog_token: u8,
780 pub rssi: i8,
782 pub rtt: u32,
784 pub t1: u64,
786 pub t2: u64,
788 pub t3: u64,
790 pub t4: u64,
792}
793
794#[derive(Debug, Clone)]
796#[cfg_attr(feature = "defmt", derive(defmt::Format))]
797#[instability::unstable]
798pub struct CredentialsInfo {
799 pub ssid: Ssid,
801 pub passphrase: [u8; 64usize],
803}
804
805#[derive(Debug, Clone)]
807pub struct Collection<T>(alloc::vec::Vec<T>);
808
809impl<T> Collection<T> {
810 pub fn as_slice(&self) -> &[T] {
812 self.0.as_slice()
813 }
814}
815
816#[cfg(feature = "defmt")]
817impl<T: defmt::Format> defmt::Format for Collection<T> {
818 fn format(&self, fmt: defmt::Formatter<'_>) {
819 self.0.iter().for_each(|v| {
820 defmt::write!(fmt, "{}", v);
821 });
822 }
823}
824
825#[derive(Debug, Clone)]
827#[cfg_attr(feature = "defmt", derive(defmt::Format))]
828#[instability::unstable]
829pub enum EventInfo {
830 WifiReady,
832
833 ScanDone {
835 status: u32,
837 number: u8,
839 scan_id: u8,
841 },
842
843 StationStart,
845
846 StationStop,
848
849 StationConnected {
851 ssid: Ssid,
853 bssid: [u8; 6usize],
855 channel: u8,
857 authmode: u32,
859 aid: u16,
861 },
862
863 StationDisconnected {
865 ssid: Ssid,
867 bssid: [u8; 6usize],
869 reason: u16,
871 rssi: i8,
873 },
874
875 StationAuthenticationModeChange {
877 old_mode: u32,
879 new_mode: u32,
881 },
882
883 StationWifiProtectedStatusEnrolleeSuccess {
885 credentials: Collection<CredentialsInfo>,
887 },
888
889 StationWifiProtectedStatusEnrolleeFailed,
891
892 StationWifiProtectedStatusEnrolleeTimeout,
894
895 StationWifiProtectedStatusEnrolleePin {
897 pin_code: [u8; 8usize],
899 },
900
901 StationWifiProtectedStatusEnrolleePushButtonConfigurationOverlap,
903
904 AccessPointStart,
906
907 AccessPointStop,
909
910 AccessPointStationConnected {
912 mac: [u8; 6usize],
914 aid: u16,
916 is_mesh_child: bool,
918 },
919
920 AccessPointStationDisconnected {
922 mac: [u8; 6usize],
924 aid: u8,
926 is_mesh_child: bool,
928 reason: u16,
930 },
931
932 AccessPointProbeRequestReceived {
934 rssi: i8,
936 mac: [u8; 6usize],
938 },
939
940 FineTimingMeasurementReport {
942 peer_mac: [u8; 6usize],
944 status: u32,
946 rtt_raw: u32,
948 rtt_est: u32,
950 dist_est: u32,
952 entries: Collection<FineTimingMeasurementReportInfo>,
954 },
955
956 StationBasicServiceSetReceivedSignalStrengthIndicatorLow {
958 rssi: i8,
960 },
961
962 ActionTransmissionStatus {
964 ifx: u32,
966 context: u32,
968 status: u32,
970 op_id: u8,
972 channel: u8,
974 },
975
976 RemainOnChannelDone {
978 context: u32,
980 status: u32,
982 op_id: u8,
984 channel: u8,
986 },
987
988 StationBeaconTimeout,
990
991 ConnectionlessModuleWakeIntervalStart,
993
994 AccessPointWifiProtectedStatusRegistrarSuccess {
996 peer_macaddr: [u8; 6usize],
998 },
999
1000 AccessPointWifiProtectedStatusRegistrarFailed {
1002 reason: u32,
1004 peer_macaddr: [u8; 6usize],
1006 },
1007
1008 AccessPointWifiProtectedStatusRegistrarTimeout,
1010
1011 AccessPointWifiProtectedStatusRegistrarPin {
1013 pin_code: [u8; 8usize],
1015 },
1016
1017 AccessPointWifiProtectedStatusRegistrarPushButtonConfigurationOverlap,
1019
1020 IndividualTargetWakeTimeSetup,
1022
1023 IndividualTargetWakeTimeTeardown,
1025
1026 IndividualTargetWakeTimeProbe,
1028
1029 IndividualTargetWakeTimeSuspend,
1031
1032 TargetWakeTimeWakeup,
1034
1035 BroadcastTargetWakeTimeSetup,
1037
1038 BroadcastTargetWakeTimeTeardown,
1040
1041 HomeChannelChange,
1044}
1045
1046impl EventInfo {
1047 pub(crate) fn from_wifi_event_raw(
1048 event: WifiEvent,
1049 payload: *mut crate::sys::c_types::c_void,
1050 ) -> Option<Self> {
1051 let enabled = WIFI_EVENT_ENABLE_MASK.with(|mask| mask.contains(event));
1052
1053 if !enabled {
1054 return None;
1055 }
1056
1057 match event {
1058 WifiEvent::WifiReady => Some(EventInfo::WifiReady),
1059 WifiEvent::ScanDone => {
1060 let ev = unsafe { ScanDone::from_raw_event_data(payload) };
1061
1062 Some(EventInfo::ScanDone {
1063 status: ev.status(),
1064 number: ev.number(),
1065 scan_id: ev.id(),
1066 })
1067 }
1068 WifiEvent::StationStart => Some(EventInfo::StationStart),
1069 WifiEvent::StationStop => Some(EventInfo::StationStop),
1070 WifiEvent::StationConnected => {
1071 let ev = unsafe { StationConnected::from_raw_event_data(payload) };
1072
1073 Some(EventInfo::StationConnected {
1074 ssid: Ssid::from_raw(ev.ssid(), ev.ssid_len()),
1075 bssid: ev.bssid().try_into().unwrap(),
1076 channel: ev.channel(),
1077 authmode: ev.authmode(),
1078 aid: ev.aid(),
1079 })
1080 }
1081 WifiEvent::StationDisconnected => {
1082 let ev = unsafe { StationDisconnected::from_raw_event_data(payload) };
1083 Some(EventInfo::StationDisconnected {
1084 ssid: Ssid::from_raw(ev.ssid(), ev.ssid_len()),
1085 bssid: ev.bssid().try_into().unwrap(),
1086 reason: ev.reason() as u16,
1087 rssi: ev.rssi(),
1088 })
1089 }
1090 WifiEvent::AccessPointStart => Some(EventInfo::AccessPointStart),
1091 WifiEvent::AccessPointStop => Some(EventInfo::AccessPointStop),
1092 WifiEvent::AccessPointStationConnected => {
1093 let ev = unsafe { AccessPointStationConnected::from_raw_event_data(payload) };
1094 Some(EventInfo::AccessPointStationConnected {
1095 mac: ev.mac().try_into().unwrap(),
1096 aid: ev.aid() as u16,
1097 is_mesh_child: ev.is_mesh_child(),
1098 })
1099 }
1100 WifiEvent::AccessPointStationDisconnected => {
1101 let ev = unsafe { AccessPointStationDisconnected::from_raw_event_data(payload) };
1102 Some(EventInfo::AccessPointStationDisconnected {
1103 mac: ev.mac().try_into().unwrap(),
1104 aid: ev.aid(),
1105 is_mesh_child: ev.is_mesh_child(),
1106 reason: ev.reason(),
1107 })
1108 }
1109 WifiEvent::StationAuthenticationModeChange => {
1110 let ev = unsafe { StationAuthenticationModeChange::from_raw_event_data(payload) };
1111 Some(EventInfo::StationAuthenticationModeChange {
1112 old_mode: ev.old_mode(),
1113 new_mode: ev.new_mode(),
1114 })
1115 }
1116 WifiEvent::StationWifiProtectedStatusEnrolleeSuccess => {
1117 let ev = unsafe {
1118 StationWifiProtectedStatusEnrolleeSuccess::from_raw_event_data(payload)
1119 };
1120 Some(EventInfo::StationWifiProtectedStatusEnrolleeSuccess {
1121 credentials: Collection(ev
1122 .access_point_cred()[..ev.access_point_cred_cnt() as usize].iter()
1123 .map(|cred| CredentialsInfo {
1124 ssid: cred.ssid().into(),
1125 passphrase: cred.passphrase().try_into().unwrap(),
1126 })
1127 .collect()),
1128 })
1129 }
1130 WifiEvent::StationWifiProtectedStatusEnrolleeFailed => {
1131 Some(EventInfo::StationWifiProtectedStatusEnrolleeFailed)
1132 }
1133 WifiEvent::StationWifiProtectedStatusEnrolleeTimeout => {
1134 Some(EventInfo::StationWifiProtectedStatusEnrolleeTimeout)
1135 }
1136 WifiEvent::StationWifiProtectedStatusEnrolleePin => {
1137 let ev =
1138 unsafe { StationWifiProtectedStatusEnrolleePin::from_raw_event_data(payload) };
1139 Some(EventInfo::StationWifiProtectedStatusEnrolleePin {
1140 pin_code: ev.pin().try_into().unwrap_or_default(),
1141 })
1142 }
1143 WifiEvent::StationWifiProtectedStatusEnrolleePushButtonConfigurationOverlap => {
1144 Some(EventInfo::StationWifiProtectedStatusEnrolleePushButtonConfigurationOverlap)
1145 }
1146 WifiEvent::AccessPointProbeRequestReceived => {
1147 let ev = unsafe { AccessPointProbeRequestReceived::from_raw_event_data(payload) };
1148 Some(EventInfo::AccessPointProbeRequestReceived {
1149 rssi: ev.rssi() as i8,
1150 mac: ev.mac().try_into().unwrap_or_default(),
1151 })
1152 }
1153 WifiEvent::FineTimingMeasurementReport => {
1154 let ev = unsafe { FineTimingMeasurementReport::from_raw_event_data(payload) };
1155 Some(EventInfo::FineTimingMeasurementReport {
1156 peer_mac: ev.peer_mac().try_into().unwrap_or_default(),
1157 status: ev.status(),
1158 rtt_raw: ev.rtt_raw(),
1159 rtt_est: ev.rtt_est(),
1160 dist_est: ev.dist_est(),
1161 entries: Collection(ev
1162 .entries()
1163 .map(|entry| FineTimingMeasurementReportInfo {
1164 dlog_token: entry.dialog_token(),
1165 rssi: entry.rssi(),
1166 rtt: entry.rtt(),
1167 t1: entry.t1(),
1168 t2: entry.t2(),
1169 t3: entry.t3(),
1170 t4: entry.t4(),
1171 })
1172 .collect()),
1173 })
1174 }
1175 WifiEvent::StationBasicServiceSetReceivedSignalStrengthIndicatorLow => {
1176 let ev = unsafe {
1177 StationBasicServiceSetReceivedSignalStrengthIndicatorLow::from_raw_event_data(
1178 payload,
1179 )
1180 };
1181 Some(
1182 EventInfo::StationBasicServiceSetReceivedSignalStrengthIndicatorLow {
1183 rssi: ev.rssi() as i8,
1184 },
1185 )
1186 }
1187 WifiEvent::ActionTransmissionStatus => {
1188 let ev = unsafe { ActionTransmissionStatus::from_raw_event_data(payload) };
1189 Some(EventInfo::ActionTransmissionStatus {
1190 ifx: ev.ifx(),
1191 context: ev.context(),
1192 status: ev.status(),
1193 op_id: ev.op_id(),
1194 channel: ev.channel(),
1195 })
1196 }
1197 WifiEvent::RemainOnChannelDone => {
1198 let ev = unsafe { RemainOnChannelDone::from_raw_event_data(payload) };
1199 Some(EventInfo::RemainOnChannelDone {
1200 context: ev.context(),
1201 status: ev.status(),
1202 op_id: ev.op_id(),
1203 channel: ev.channel(),
1204 })
1205 }
1206 WifiEvent::StationBeaconTimeout => Some(EventInfo::StationBeaconTimeout),
1207 WifiEvent::ConnectionlessModuleWakeIntervalStart => {
1208 Some(EventInfo::ConnectionlessModuleWakeIntervalStart)
1209 }
1210 WifiEvent::AccessPointWifiProtectedStatusRegistrarSuccess => {
1211 let ev = unsafe {
1212 AccessPointWifiProtectedStatusRegistrarSuccess::from_raw_event_data(payload)
1213 };
1214 Some(EventInfo::AccessPointWifiProtectedStatusRegistrarSuccess {
1215 peer_macaddr: ev.peer_mac().try_into().unwrap_or_default(),
1216 })
1217 }
1218 WifiEvent::AccessPointWifiProtectedStatusRegistrarFailed => {
1219 let ev = unsafe {
1220 AccessPointWifiProtectedStatusRegistrarFailed::from_raw_event_data(payload)
1221 };
1222 Some(EventInfo::AccessPointWifiProtectedStatusRegistrarFailed {
1223 reason: ev.reason(),
1224 peer_macaddr: *ev.peer_macaddr(),
1225 })
1226 }
1227 WifiEvent::AccessPointWifiProtectedStatusRegistrarTimeout => {
1228 Some(EventInfo::AccessPointWifiProtectedStatusRegistrarTimeout)
1229 }
1230 WifiEvent::AccessPointWifiProtectedStatusRegistrarPin => {
1231 let ev = unsafe {
1232 AccessPointWifiProtectedStatusRegistrarPin::from_raw_event_data(payload)
1233 };
1234 Some(EventInfo::AccessPointWifiProtectedStatusRegistrarPin {
1235 pin_code: ev.pin_code().try_into().unwrap_or_default(),
1236 })
1237 }
1238 WifiEvent::AccessPointWifiProtectedStatusRegistrarPushButtonConfigurationOverlap => {
1239 Some(EventInfo::AccessPointWifiProtectedStatusRegistrarPushButtonConfigurationOverlap)
1240 }
1241 WifiEvent::IndividualTargetWakeTimeSetup => {
1242 Some(EventInfo::IndividualTargetWakeTimeSetup)
1243 }
1244 WifiEvent::IndividualTargetWakeTimeTeardown => {
1245 Some(EventInfo::IndividualTargetWakeTimeTeardown)
1246 }
1247 WifiEvent::IndividualTargetWakeTimeProbe => {
1248 Some(EventInfo::IndividualTargetWakeTimeProbe)
1249 }
1250 WifiEvent::IndividualTargetWakeTimeSuspend => {
1251 Some(EventInfo::IndividualTargetWakeTimeSuspend)
1252 }
1253 WifiEvent::TargetWakeTimeWakeup => {
1254 Some(EventInfo::TargetWakeTimeWakeup)
1255 }
1256 WifiEvent::BroadcastTargetWakeTimeSetup => {
1257 Some(EventInfo::BroadcastTargetWakeTimeSetup)
1258 }
1259 WifiEvent::BroadcastTargetWakeTimeTeardown => {
1260 Some(EventInfo::BroadcastTargetWakeTimeTeardown)
1261 }
1262 WifiEvent::HomeChannelChange => {
1263 Some(EventInfo::HomeChannelChange)
1264 }
1265 _ => None,
1266 }
1267 }
1268}
1269
1270#[instability::unstable]
1272pub fn enable_wifi_events(events: EnumSet<WifiEvent>) {
1273 WIFI_EVENT_ENABLE_MASK.with(|mask| *mask |= events);
1274}
1275
1276#[instability::unstable]
1294pub fn disable_wifi_events(events: EnumSet<WifiEvent>) {
1295 WIFI_EVENT_ENABLE_MASK.with(|mask| *mask &= !events);
1296}
1297
1298#[derive(Debug, Clone)]
1300#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1301#[instability::unstable]
1302pub enum MessageResult {
1303 Lagged(u64),
1306 Message(EventInfo),
1308}
1309
1310#[instability::unstable]
1312pub struct EventSubscriber<'a> {
1313 inner: embassy_sync::pubsub::Subscriber<
1314 'a,
1315 esp_sync::RawMutex,
1316 EventInfo,
1317 { esp_config_int!(usize, "ESP_RADIO_CONFIG_EVENT_CHANNEL_CAPACITY") },
1318 { esp_config_int!(usize, "ESP_RADIO_CONFIG_EVENT_CHANNEL_SUBSCRIBERS") },
1319 1,
1320 >,
1321}
1322
1323impl<'a> EventSubscriber<'a> {
1324 pub(crate) fn new(
1325 subscriber: embassy_sync::pubsub::Subscriber<
1326 'a,
1327 esp_sync::RawMutex,
1328 EventInfo,
1329 { esp_config_int!(usize, "ESP_RADIO_CONFIG_EVENT_CHANNEL_CAPACITY") },
1330 { esp_config_int!(usize, "ESP_RADIO_CONFIG_EVENT_CHANNEL_SUBSCRIBERS") },
1331 1,
1332 >,
1333 ) -> Self {
1334 Self { inner: subscriber }
1335 }
1336
1337 #[instability::unstable]
1339 pub async fn next_event(&mut self) -> MessageResult {
1340 match self.inner.next_message().await {
1341 embassy_sync::pubsub::WaitResult::Lagged(missed) => MessageResult::Lagged(missed),
1342 embassy_sync::pubsub::WaitResult::Message(msg) => MessageResult::Message(msg),
1343 }
1344 }
1345
1346 #[instability::unstable]
1348 pub async fn next_event_pure(&mut self) -> EventInfo {
1349 self.inner.next_message_pure().await
1350 }
1351}