Skip to main content

esp_radio/wifi/
event.rs

1//! Wi-Fi Events
2//!
3//! This is considered unstable functionality.
4//! Use with caution.
5
6use 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/// Events generated by the Wi-Fi driver.
25#[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    /// Wi-Fi is ready for operation.
32    WifiReady = 0,
33    /// Scan operation has completed.
34    ScanDone,
35    /// Station mode started.
36    StationStart,
37    /// Station mode stopped.
38    StationStop,
39    /// Station connected to a network.
40    StationConnected,
41    /// Station disconnected from a network.
42    StationDisconnected,
43    /// Station authentication mode changed.
44    StationAuthenticationModeChange,
45
46    /// Station Wi-Fi-Protected-Status succeeds in enrollee mode.
47    StationWifiProtectedStatusEnrolleeSuccess,
48    /// Station Wi-Fi-Protected-Status fails in enrollee mode.
49    StationWifiProtectedStatusEnrolleeFailed,
50    /// Station Wi-Fi-Protected-Status timeout in enrollee mode.
51    StationWifiProtectedStatusEnrolleeTimeout,
52    /// Station Wi-Fi-Protected-Status pin code in enrollee mode.
53    StationWifiProtectedStatusEnrolleePin,
54    /// Station Wi-Fi-Protected-Status overlap in enrollee mode.
55    StationWifiProtectedStatusEnrolleePushButtonConfigurationOverlap,
56
57    /// Soft-AccessPoint start.
58    AccessPointStart,
59    /// Soft-AccessPoint stop.
60    AccessPointStop,
61    /// A station connected to Soft-AccessPoint.
62    AccessPointStationConnected,
63    /// A station disconnected from Soft-AccessPoint.
64    AccessPointStationDisconnected,
65    /// Received probe request packet in Soft-AccessPoint interface.
66    AccessPointProbeRequestReceived,
67
68    /// Received report of Fine-Timing-Measurement procedure.
69    FineTimingMeasurementReport,
70
71    /// Station Receive-Signal-Strenght-Indicator goes below the configured threshold.
72    StationBasicServiceSetReceivedSignalStrengthIndicatorLow,
73    /// Status indication of Action Transmission operation.
74    ActionTransmissionStatus,
75    /// Remain-on-Channel operation complete.
76    RemainOnChannelDone,
77
78    /// Station beacon timeout.
79    StationBeaconTimeout,
80
81    /// Connectionless module wake interval has started.
82    ConnectionlessModuleWakeIntervalStart,
83
84    /// Soft-AccessPoint Wi-Fi-Protected-Status succeeded in registrar mode.
85    AccessPointWifiProtectedStatusRegistrarSuccess,
86    /// Soft-AccessPoint Wi-Fi-Protected-Status failed in registrar mode.
87    AccessPointWifiProtectedStatusRegistrarFailed,
88    /// Soft-AccessPoint Wi-Fi-Protected-Status timed out in registrar mode.
89    AccessPointWifiProtectedStatusRegistrarTimeout,
90    /// Soft-AccessPoint Wi-Fi-Protected-Status pin code in registrar mode.
91    AccessPointWifiProtectedStatusRegistrarPin,
92    /// Soft-AccessPoint Wi-Fi-Protected-Status overlap in registrar mode.
93    AccessPointWifiProtectedStatusRegistrarPushButtonConfigurationOverlap,
94
95    /// Individual Target-Wake-Time setup.
96    IndividualTargetWakeTimeSetup,
97    /// Individual Target-Wake-Time teardown.
98    IndividualTargetWakeTimeTeardown,
99    /// Individual Target-Wake-Time probe.
100    IndividualTargetWakeTimeProbe,
101    /// Individual Target-Wake-Time suspended.
102    IndividualTargetWakeTimeSuspend,
103    /// Target-Wake-Wakeup event.
104    TargetWakeTimeWakeup,
105    /// Broadcast-Target-Wake-Time setup.
106    BroadcastTargetWakeTimeSetup,
107    /// Broadcast-Target-Wake-Time teardown.
108    BroadcastTargetWakeTimeTeardown,
109
110    /// Neighbor-Awareness-Networking discovery has started.
111    NeighborAwarenessNetworkingStarted,
112    /// Neighbor-Awareness-Networking discovery has stopped.
113    NeighborAwarenessNetworkingStopped,
114    /// Neighbor-Awareness-Networking service discovery match found.
115    NeighborAwarenessNetworkingServiceMatch,
116    /// Replied to a Neighbor-Awareness-Networking peer with service discovery match.
117    NeighborAwarenessNetworkingReplied,
118    /// Received a follow-up message in Neighbor-Awareness-Networking.
119    NeighborAwarenessNetworkingReceive,
120    /// Received NDP (Neighbor Discovery Protocol) request from a Neighbor-Awareness-Networking
121    /// peer.
122    NeighborDiscoveryProtocolIndication,
123    /// NDP confirm indication.
124    NeighborDiscoveryProtocolConfirmation,
125    /// Neighbor-Awareness-Networking datapath terminated indication.
126    NeighborDiscoveryProtocolTerminated,
127    /// Wi-Fi home channel change, doesn't occur when scanning.
128    HomeChannelChange,
129
130    /// Received Neighbor Report response.
131    StationNeighborRep,
132}
133
134trait Event {
135    /// # Safety
136    /// `ptr` must be a valid for casting to this event's inner event data.
137    unsafe fn from_raw_event_data(ptr: *mut crate::sys::c_types::c_void) -> Self;
138}
139
140macro_rules! impl_wifi_event {
141    // no data
142    ($newtype:ident) => {
143        /// See [`WifiEvent`].
144        #[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        /// See [`WifiEvent`].
158        #[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    /// Get the MAC address of the connected station.
262    pub fn mac(&self) -> &[u8] {
263        &self.0.mac
264    }
265
266    /// Get the AID (Association Identifier) of the connected station.
267    pub fn aid(&self) -> u8 {
268        self.0.aid
269    }
270
271    /// Flag indicating whether the connected station is a mesh child.
272    pub fn is_mesh_child(&self) -> bool {
273        self.0.is_mesh_child
274    }
275}
276
277impl AccessPointStationDisconnected<'_> {
278    /// Get the MAC address of the disconnected station.
279    pub fn mac(&self) -> &[u8] {
280        &self.0.mac
281    }
282
283    /// Get the reason for the disconnection.
284    pub fn reason(&self) -> u16 {
285        self.0.reason
286    }
287
288    /// AID that the Soft-AccessPoint assigned to the disconnected station.
289    pub fn aid(&self) -> u8 {
290        self.0.aid
291    }
292
293    /// Flag indicating whether the connected station is a mesh child.
294    pub fn is_mesh_child(&self) -> bool {
295        self.0.is_mesh_child
296    }
297}
298
299impl ScanDone<'_> {
300    /// Get the status of the scan operation.
301    pub fn status(&self) -> u32 {
302        self.0.status
303    }
304
305    /// Get the number of found APs.
306    pub fn number(&self) -> u8 {
307        self.0.number
308    }
309
310    /// Get the scan ID associated with this scan operation.
311    pub fn id(&self) -> u8 {
312        self.0.scan_id
313    }
314}
315
316impl StationConnected<'_> {
317    /// Get the SSID of the connected station.
318    pub fn ssid(&self) -> &[u8] {
319        &self.0.ssid
320    }
321
322    /// Get the length of the SSID.
323    pub fn ssid_len(&self) -> u8 {
324        self.0.ssid_len
325    }
326
327    /// Get the BSSID (MAC address) of the connected station.
328    pub fn bssid(&self) -> &[u8] {
329        &self.0.bssid
330    }
331
332    /// Get the channel on which the station is connected.
333    pub fn channel(&self) -> u8 {
334        self.0.channel
335    }
336
337    /// Get the authentication mode used for the connection.
338    pub fn authmode(&self) -> u32 {
339        self.0.authmode
340    }
341
342    /// Get the AID (Association Identifier) of the connected station.
343    pub fn aid(&self) -> u16 {
344        self.0.aid
345    }
346}
347
348impl StationDisconnected<'_> {
349    /// Get the SSID of the disconnected station.
350    pub fn ssid(&self) -> &[u8] {
351        &self.0.ssid
352    }
353
354    /// Get the length of the SSID.
355    pub fn ssid_len(&self) -> u8 {
356        self.0.ssid_len
357    }
358
359    /// Get the BSSID (MAC address) of the disconnected station.
360    pub fn bssid(&self) -> &[u8] {
361        &self.0.bssid
362    }
363
364    /// Get the reason for the disconnection.
365    pub fn reason(&self) -> u8 {
366        self.0.reason
367    }
368
369    /// Get the authentication mode used for the disconnection.
370    pub fn rssi(&self) -> i8 {
371        self.0.rssi
372    }
373}
374
375impl AccessPointCredential<'_> {
376    /// Get the SSID of an access point.
377    pub fn ssid(&self) -> &[u8] {
378        &self.0.ssid
379    }
380
381    /// Get passphrase for the access point.
382    pub fn passphrase(&self) -> &[u8] {
383        &self.0.passphrase
384    }
385}
386
387impl StationAuthenticationModeChange<'_> {
388    /// Get the old authentication mode.
389    pub fn old_mode(&self) -> u32 {
390        self.0.old_mode
391    }
392
393    /// Get the new authentication mode.
394    pub fn new_mode(&self) -> u32 {
395        self.0.new_mode
396    }
397}
398
399impl StationWifiProtectedStatusEnrolleeSuccess<'_> {
400    /// Get number of access point credentials received.
401    pub fn access_point_cred_cnt(&self) -> u8 {
402        self.0.ap_cred_cnt
403    }
404
405    /// Get all access point credentials received.
406    pub fn access_point_cred(&self) -> &[AccessPointCredential<'_>] {
407        let array_ref: &[AccessPointCredential<'_>; 3] =
408            // cast reference of fixed-size array to wrapper type
409            unsafe { &*(&self.0.ap_cred as *const _ as *const [AccessPointCredential<'_>; 3]) };
410
411        &array_ref[..]
412    }
413}
414
415impl StationWifiProtectedStatusEnrolleePin<'_> {
416    /// Get the PIN code received from the WPS.
417    pub fn pin(&self) -> &[u8] {
418        &self.0.pin_code
419    }
420}
421
422impl FineTimingMeasurementReportEntry<'_> {
423    /// Gets the Dialog Token of the FTM frame.
424    pub fn dialog_token(&self) -> u8 {
425        self.0.dlog_token
426    }
427
428    /// Gets the Received Signal Strength Indicator (RSSI) of the FTM frame.
429    pub fn rssi(&self) -> i8 {
430        self.0.rssi
431    }
432
433    /// Gets the Round Trip Time (RTT) in picoseconds.
434    pub fn rtt(&self) -> u32 {
435        self.0.rtt
436    }
437
438    /// Gets T1: Time of departure of the FTM frame from the Responder (in picoseconds).
439    pub fn t1(&self) -> u64 {
440        self.0.t1
441    }
442
443    /// Gets T2: Time of arrival of the FTM frame at the Initiator (in picoseconds).
444    pub fn t2(&self) -> u64 {
445        self.0.t2
446    }
447
448    /// Gets T3: Time of departure of the ACK from the Initiator (in picoseconds).
449    pub fn t3(&self) -> u64 {
450        self.0.t3
451    }
452
453    /// Gets T4: Time of arrival of the ACK at the Responder (in picoseconds).
454    pub fn t4(&self) -> u64 {
455        self.0.t4
456    }
457}
458
459impl FineTimingMeasurementReport<'_> {
460    /// Get the MAC address of the FTM peer.
461    pub fn peer_mac(&self) -> &[u8] {
462        &self.0.peer_mac
463    }
464
465    /// Get the status of the FTM operation.
466    pub fn status(&self) -> u32 {
467        self.0.status
468    }
469
470    /// Get the raw round-trip time (RTT) in nanoseconds.
471    pub fn rtt_raw(&self) -> u32 {
472        self.0.rtt_raw
473    }
474
475    /// Get the estimated round-trip time (RTT) in nanoseconds.
476    pub fn rtt_est(&self) -> u32 {
477        self.0.rtt_est
478    }
479
480    /// Get the distance estimate in centimeters.
481    pub fn dist_est(&self) -> u32 {
482        self.0.dist_est
483    }
484
485    /// Get the number of entries in the FTM report data.
486    pub fn report_num_entries(&self) -> u8 {
487        self.0.ftm_report_num_entries
488    }
489
490    /// Returns an iterator over the detailed FTM report entries.
491    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        // Return an empty slice when there are no entries.
496        let entries_slice = if ptr.is_null() || len == 0 {
497            &[]
498        } else {
499            // Otherwise, it's the slice from the data.
500            // Can we trust the C API to provide a valid pointer and length?
501            unsafe { core::slice::from_raw_parts(ptr, len) }
502        };
503
504        entries_slice.iter().map(FineTimingMeasurementReportEntry)
505    }
506}
507
508impl AccessPointProbeRequestReceived<'_> {
509    /// Get received probe request SSID.
510    pub fn rssi(&self) -> i32 {
511        self.0.rssi
512    }
513
514    /// Get the MAC address of the station which send probe request.
515    pub fn mac(&self) -> &[u8] {
516        &self.0.mac
517    }
518}
519
520impl StationBasicServiceSetReceivedSignalStrengthIndicatorLow<'_> {
521    /// Get received probe request SSID of bss.
522    pub fn rssi(&self) -> i32 {
523        self.0.rssi
524    }
525}
526
527impl ActionTransmissionStatus<'_> {
528    /// Get Wi-Fi interface to send request to.
529    pub fn ifx(&self) -> u32 {
530        self.0.ifx
531    }
532
533    /// Get context to identify the request.
534    pub fn context(&self) -> u32 {
535        self.0.context
536    }
537
538    /// ID of the corresponding operation that was provided during action tx request.
539    pub fn op_id(&self) -> u8 {
540        self.0.op_id
541    }
542
543    /// Channel provided in tx request.
544    pub fn channel(&self) -> u8 {
545        self.0.channel
546    }
547
548    /// Get the status of the operation.
549    pub fn status(&self) -> u32 {
550        self.0.status
551    }
552}
553
554impl RemainOnChannelDone<'_> {
555    /// Get context to identify the request.
556    pub fn context(&self) -> u32 {
557        self.0.context
558    }
559
560    /// Get the status of the operation.
561    pub fn status(&self) -> u32 {
562        self.0.status
563    }
564
565    /// ID of the corresponding operation.
566    pub fn op_id(&self) -> u8 {
567        self.0.op_id
568    }
569
570    /// Channel provided.
571    pub fn channel(&self) -> u8 {
572        self.0.channel
573    }
574}
575
576impl AccessPointWifiProtectedStatusRegistrarSuccess<'_> {
577    /// Get enrollee mac address.
578    pub fn peer_mac(&self) -> &[u8] {
579        &self.0.peer_macaddr
580    }
581}
582
583impl AccessPointWifiProtectedStatusRegistrarFailed<'_> {
584    /// Get WPS failure reason.
585    pub fn reason(&self) -> u32 {
586        self.0.reason
587    }
588
589    /// Get enrollee mac address.
590    pub fn peer_macaddr(&self) -> &[u8; 6] {
591        &self.0.peer_macaddr
592    }
593}
594
595impl AccessPointWifiProtectedStatusRegistrarPin<'_> {
596    /// Get the PIN code of station in enrollee mode.
597    pub fn pin_code(&self) -> &[u8] {
598        &self.0.pin_code
599    }
600}
601
602impl NeighborAwarenessNetworkingServiceMatch<'_> {
603    /// Get the Subscribe Service ID.
604    pub fn subscribe_id(&self) -> u8 {
605        self.0.subscribe_id
606    }
607
608    /// Get the Publish Service ID.
609    pub fn publish_id(&self) -> u8 {
610        self.0.publish_id
611    }
612
613    /// Get the NAN Interface MAC of the Publisher.
614    pub fn pub_if_mac(&self) -> &[u8] {
615        &self.0.pub_if_mac
616    }
617
618    /// Indicates whether publisher’s service ID needs to be updated.
619    pub fn update_pub_id(&self) -> bool {
620        self.0.update_pub_id
621    }
622}
623
624impl NeighborAwarenessNetworkingReplied<'_> {
625    /// Get the Subscribe Service ID.
626    pub fn subscribe_id(&self) -> u8 {
627        self.0.subscribe_id
628    }
629
630    /// Get the Publish Service ID.
631    pub fn publish_id(&self) -> u8 {
632        self.0.publish_id
633    }
634
635    /// Get the NAN Interface MAC of the Subscriber.
636    pub fn sub_if_mac(&self) -> &[u8] {
637        &self.0.sub_if_mac
638    }
639}
640
641impl NeighborAwarenessNetworkingReceive<'_> {
642    /// Get Our Service Identifier.
643    pub fn inst_id(&self) -> u8 {
644        self.0.inst_id
645    }
646
647    /// Get Peer's Service Identifier.
648    pub fn peer_inst_id(&self) -> u8 {
649        self.0.peer_inst_id
650    }
651
652    /// Get Peer’s NAN Interface MAC
653    pub fn peer_if_mac(&self) -> &[u8; 6] {
654        &self.0.peer_if_mac
655    }
656
657    /// Get Peer Service Info.
658    pub fn peer_svc_info(&self) -> &[u8; 64] {
659        &self.0.peer_svc_info
660    }
661}
662
663impl NeighborDiscoveryProtocolIndication<'_> {
664    /// Get Publish ID for NAN Service.
665    pub fn publish_id(&self) -> u8 {
666        self.0.publish_id
667    }
668
669    /// Get NDF instance ID.
670    pub fn ndp_id(&self) -> u8 {
671        self.0.ndp_id
672    }
673
674    /// Get Peer’s NAN Interface MAC.
675    pub fn peer_nmi(&self) -> &[u8; 6] {
676        &self.0.peer_nmi
677    }
678
679    /// Get Peer’s NAN Data Interface MAC.
680    pub fn peer_ndi(&self) -> &[u8; 6] {
681        &self.0.peer_ndi
682    }
683
684    /// Get Service Specific Info.
685    pub fn svc_info(&self) -> &[u8; 64] {
686        &self.0.svc_info
687    }
688}
689
690impl NeighborDiscoveryProtocolConfirmation<'_> {
691    /// Get NDP status code.
692    pub fn status(&self) -> u8 {
693        self.0.status
694    }
695
696    /// Get NDP instance ID.
697    pub fn id(&self) -> u8 {
698        self.0.ndp_id
699    }
700
701    /// Get Peer’s NAN Management Interface MAC.
702    pub fn peer_nmi(&self) -> &[u8; 6] {
703        &self.0.peer_nmi
704    }
705
706    /// Get Peer’s NAN Data Interface MAC.
707    pub fn peer_ndi(&self) -> &[u8; 6] {
708        &self.0.peer_ndi
709    }
710
711    /// Get Own NAN Data Interface MAC.
712    pub fn own_ndi(&self) -> &[u8; 6] {
713        &self.0.own_ndi
714    }
715
716    /// Get Service Specific Info.
717    pub fn svc_info(&self) -> &[u8; 64] {
718        &self.0.svc_info
719    }
720}
721
722impl NeighborDiscoveryProtocolTerminated<'_> {
723    /// Get termination reason code.
724    pub fn reason(&self) -> u8 {
725        self.0.reason
726    }
727
728    /// Get NDP instance ID.
729    pub fn id(&self) -> u8 {
730        self.0.ndp_id
731    }
732
733    /// Get Initiator’s NAN Data Interface MAC
734    pub fn init_ndi(&self) -> &[u8; 6] {
735        &self.0.init_ndi
736    }
737}
738
739impl HomeChannelChange<'_> {
740    /// Get the old home channel of the device.
741    pub fn old_chan(&self) -> u8 {
742        self.0.old_chan
743    }
744
745    /// Get the old second channel of the device.
746    pub fn old_snd(&self) -> u32 {
747        self.0.old_snd
748    }
749
750    /// Get the new home channel of the device.
751    pub fn new_chan(&self) -> u8 {
752        self.0.new_chan
753    }
754
755    /// Get the new second channel of the device.
756    pub fn new_snd(&self) -> u32 {
757        self.0.new_snd
758    }
759}
760
761impl StationNeighborRep<'_> {
762    /// Get the Neighbor Report received from the access point.
763    pub fn report(&self) -> &[u8] {
764        &self.0.report[..self.0.report_len as usize]
765    }
766
767    /// Get the length of report.
768    pub fn report_len(&self) -> u16 {
769        self.0.report_len
770    }
771}
772
773/// Detailed FTM report entry.
774#[derive(Debug, Clone)]
775#[cfg_attr(feature = "defmt", derive(defmt::Format))]
776#[instability::unstable]
777pub struct FineTimingMeasurementReportInfo {
778    /// Dialog Token of the FTM frame
779    pub dlog_token: u8,
780    /// RSSI of the FTM frame received
781    pub rssi: i8,
782    /// Round Trip Time in pSec with a peer
783    pub rtt: u32,
784    /// Time of departure of FTM frame from FTM Responder in pSec
785    pub t1: u64,
786    /// Time of arrival of FTM frame at FTM Initiator in pSec
787    pub t2: u64,
788    /// Time of departure of ACK from FTM Initiator in pSec
789    pub t3: u64,
790    /// Time of arrival of ACK at FTM Responder in pSec
791    pub t4: u64,
792}
793
794/// Credential info record.
795#[derive(Debug, Clone)]
796#[cfg_attr(feature = "defmt", derive(defmt::Format))]
797#[instability::unstable]
798pub struct CredentialsInfo {
799    /// SSID of AP
800    pub ssid: Ssid,
801    /// Passphrase for the AP
802    pub passphrase: [u8; 64usize],
803}
804
805/// A collection of elements.
806#[derive(Debug, Clone)]
807pub struct Collection<T>(alloc::vec::Vec<T>);
808
809impl<T> Collection<T> {
810    /// The elements of this collection.
811    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/// Event including the payload.
826#[derive(Debug, Clone)]
827#[cfg_attr(feature = "defmt", derive(defmt::Format))]
828#[instability::unstable]
829pub enum EventInfo {
830    /// Wi-Fi is ready for operation.
831    WifiReady,
832
833    /// Scan operation has completed.
834    ScanDone {
835        /// Status of scanning APs: 0 — success, 1 - failure
836        status: u32,
837        /// Number of scan results
838        number: u8,
839        /// Scan sequence number, used for block scan
840        scan_id: u8,
841    },
842
843    /// Station mode started.
844    StationStart,
845
846    /// Station mode stopped.
847    StationStop,
848
849    /// Station connected to a network.
850    StationConnected {
851        /// SSID of connected AP
852        ssid: Ssid,
853        /// BSSID of connected AP
854        bssid: [u8; 6usize],
855        /// Channel of connected AP
856        channel: u8,
857        /// Authentication mode used by the connection
858        authmode: u32,
859        /// Authentication id assigned by the connected AP
860        aid: u16,
861    },
862
863    /// Station disconnected from a network.
864    StationDisconnected {
865        /// SSID of disconnected AP
866        ssid: Ssid,
867        /// BSSID of disconnected AP
868        bssid: [u8; 6usize],
869        /// Disconnection reason
870        reason: u16,
871        /// Disconnection RSSI
872        rssi: i8,
873    },
874
875    /// Station authentication mode changed.
876    StationAuthenticationModeChange {
877        /// Old auth mode of AP
878        old_mode: u32,
879        /// New auth mode of AP
880        new_mode: u32,
881    },
882
883    /// Station Wi-Fi-Protected-Status succeeds in enrollee mode.
884    StationWifiProtectedStatusEnrolleeSuccess {
885        /// Credentials
886        credentials: Collection<CredentialsInfo>,
887    },
888
889    /// Station Wi-Fi-Protected-Status fails in enrollee mode.
890    StationWifiProtectedStatusEnrolleeFailed,
891
892    /// Station Wi-Fi-Protected-Status timeout in enrollee mode.
893    StationWifiProtectedStatusEnrolleeTimeout,
894
895    /// Station Wi-Fi-Protected-Status pin code in enrollee mode.
896    StationWifiProtectedStatusEnrolleePin {
897        /// PIN code of station in enrollee mode
898        pin_code: [u8; 8usize],
899    },
900
901    /// Station Wi-Fi-Protected-Status overlap in enrollee mode.
902    StationWifiProtectedStatusEnrolleePushButtonConfigurationOverlap,
903
904    /// Soft-AccessPoint start.
905    AccessPointStart,
906
907    /// Soft-AccessPoint stop.
908    AccessPointStop,
909
910    /// A station connected to Soft-AccessPoint.
911    AccessPointStationConnected {
912        /// MAC address of the station connected to Soft-AP
913        mac: [u8; 6usize],
914        /// AID assigned by the Soft-AP to the connected station
915        aid: u16,
916        /// Flag indicating whether the connected station is a mesh child
917        is_mesh_child: bool,
918    },
919
920    /// A station disconnected from Soft-AccessPoint.
921    AccessPointStationDisconnected {
922        /// MAC address of the station disconnects from the soft-AP
923        mac: [u8; 6usize],
924        /// AID that the Soft-AP assigned to the disconnected station
925        aid: u8,
926        /// Flag indicating whether the disconnected station is a mesh child
927        is_mesh_child: bool,
928        /// Disconnection reason
929        reason: u16,
930    },
931
932    /// Received probe request packet in Soft-AccessPoint interface.
933    AccessPointProbeRequestReceived {
934        /// Received probe request signal strength
935        rssi: i8,
936        /// MAC address of the station which send probe request
937        mac: [u8; 6usize],
938    },
939
940    /// Received report of Fine-Timing-Measurement procedure.
941    FineTimingMeasurementReport {
942        /// MAC address of the FTM Peer
943        peer_mac: [u8; 6usize],
944        /// Status of the FTM operation
945        status: u32,
946        /// Raw average Round-Trip-Time with peer in Nano-Seconds
947        rtt_raw: u32,
948        /// Estimated Round-Trip-Time with peer in Nano-Seconds
949        rtt_est: u32,
950        /// Estimated one-way distance in Centi-Meters
951        dist_est: u32,
952        /// Detailed FTM report entries.
953        entries: Collection<FineTimingMeasurementReportInfo>,
954    },
955
956    /// Station Receive-Signal-Strenght-Indicator goes below the configured threshold.
957    StationBasicServiceSetReceivedSignalStrengthIndicatorLow {
958        /// RSSI value of bss
959        rssi: i8,
960    },
961
962    /// Status indication of Action Transmission operation.
963    ActionTransmissionStatus {
964        /// WiFi interface to send request to
965        ifx: u32,
966        /// Context to identify the request
967        context: u32,
968        /// Status of the operation
969        status: u32,
970        /// ID of the corresponding operation that was provided during action tx request
971        op_id: u8,
972        /// Channel provided in tx request
973        channel: u8,
974    },
975
976    /// Remain-on-Channel operation complete.
977    RemainOnChannelDone {
978        /// Context to identify the initiator of the request
979        context: u32,
980        /// ROC status
981        status: u32,
982        /// ID of the corresponding ROC operation
983        op_id: u8,
984        /// Channel provided in tx request
985        channel: u8,
986    },
987
988    /// Station beacon timeout.
989    StationBeaconTimeout,
990
991    /// Connectionless module wake interval has started.
992    ConnectionlessModuleWakeIntervalStart,
993
994    /// Soft-AccessPoint Wi-Fi-Protected-Status succeeded in registrar mode.
995    AccessPointWifiProtectedStatusRegistrarSuccess {
996        /// Enrollee mac address
997        peer_macaddr: [u8; 6usize],
998    },
999
1000    /// Soft-AccessPoint Wi-Fi-Protected-Status failed in registrar mode.
1001    AccessPointWifiProtectedStatusRegistrarFailed {
1002        /// WPS failure reason wps_fail_reason_t
1003        reason: u32,
1004        /// Enrollee mac address
1005        peer_macaddr: [u8; 6usize],
1006    },
1007
1008    /// Soft-AccessPoint Wi-Fi-Protected-Status timed out in registrar mode.
1009    AccessPointWifiProtectedStatusRegistrarTimeout,
1010
1011    /// Soft-AccessPoint Wi-Fi-Protected-Status pin code in registrar mode.
1012    AccessPointWifiProtectedStatusRegistrarPin {
1013        /// PIN code of station in enrollee mode
1014        pin_code: [u8; 8usize],
1015    },
1016
1017    /// Soft-AccessPoint Wi-Fi-Protected-Status overlap in registrar mode.
1018    AccessPointWifiProtectedStatusRegistrarPushButtonConfigurationOverlap,
1019
1020    /// Individual Target-Wake-Time setup.
1021    IndividualTargetWakeTimeSetup,
1022
1023    /// Individual Target-Wake-Time teardown.
1024    IndividualTargetWakeTimeTeardown,
1025
1026    /// Individual Target-Wake-Time probe.
1027    IndividualTargetWakeTimeProbe,
1028
1029    /// Individual Target-Wake-Time suspended.
1030    IndividualTargetWakeTimeSuspend,
1031
1032    /// Target-Wake-Wakeup event.
1033    TargetWakeTimeWakeup,
1034
1035    /// Broadcast-Target-Wake-Time setup.
1036    BroadcastTargetWakeTimeSetup,
1037
1038    /// Broadcast-Target-Wake-Time teardown.
1039    BroadcastTargetWakeTimeTeardown,
1040
1041    // we don't currently support NAN - and there is no intention right now to change that
1042    /// Wi-Fi home channel change, doesn't occur when scanning.
1043    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/// Enable the given events.
1271#[instability::unstable]
1272pub fn enable_wifi_events(events: EnumSet<WifiEvent>) {
1273    WIFI_EVENT_ENABLE_MASK.with(|mask| *mask |= events);
1274}
1275
1276/// Disable the given events.
1277///
1278/// # Attention
1279/// Disabling events which are used internally will cause problems.
1280///
1281/// Therefore you usually don't want to disable these:
1282/// - [WifiEvent::StationStart]
1283/// - [WifiEvent::StationStop]
1284/// - [WifiEvent::StationConnected]
1285/// - [WifiEvent::StationDisconnected]
1286/// - [WifiEvent::AccessPointStart]
1287/// - [WifiEvent::AccessPointStop]
1288/// - [WifiEvent::AccessPointStationConnected]
1289/// - [WifiEvent::AccessPointStationDisconnected]
1290/// - [WifiEvent::ScanDone]
1291///
1292/// [crate::wifi::new] always enables these events, even if they were disabled beforehand.
1293#[instability::unstable]
1294pub fn disable_wifi_events(events: EnumSet<WifiEvent>) {
1295    WIFI_EVENT_ENABLE_MASK.with(|mask| *mask &= !events);
1296}
1297
1298/// Result for [EventSubscriber::next_message].
1299#[derive(Debug, Clone)]
1300#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1301#[instability::unstable]
1302pub enum MessageResult {
1303    /// The subscriber did not receive all messages and lagged by the given amount of messages.
1304    /// (This is the amount of messages that were missed)
1305    Lagged(u64),
1306    /// The received event.
1307    Message(EventInfo),
1308}
1309
1310/// Event subscriber.
1311#[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    /// Wait for a published event
1338    #[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    /// Wait for a published event (ignoring lag results)
1347    #[instability::unstable]
1348    pub async fn next_event_pure(&mut self) -> EventInfo {
1349        self.inner.next_message_pure().await
1350    }
1351}