1use alloc::boxed::Box;
2
3use esp_hal::sync::Locked;
4
5use super::WifiEvent;
6
7pub(crate) mod sealed {
8 use super::*;
9
10 pub trait Event {
11 fn handler() -> &'static Locked<Option<Box<Handler<Self>>>>;
13 unsafe fn from_raw_event_data(ptr: *mut crate::binary::c_types::c_void) -> Self;
16 }
17}
18pub type Handler<T> = dyn FnMut(&T) + Sync + Send;
20
21fn default_handler<Event: 'static>() -> Box<Handler<Event>> {
22 fn drop_ref<T>(_: &T) {}
23 Box::new(drop_ref)
26}
27
28pub trait EventExt: sealed::Event + Sized + 'static {
44 fn take_handler() -> Box<Handler<Self>> {
46 Self::handler().with(|handler| handler.take().unwrap_or_else(default_handler::<Self>))
47 }
48 fn replace_handler<F: FnMut(&Self) + Sync + Send + 'static>(f: F) -> Box<Handler<Self>> {
50 Self::handler().with(|handler| {
51 handler
52 .replace(Box::new(f))
53 .unwrap_or_else(default_handler::<Self>)
54 })
55 }
56 fn update_handler<F: FnMut(&Self) + Sync + Send + 'static>(mut f: F) {
60 Self::handler().with(|handler| {
61 let mut prev: Box<Handler<Self>> =
62 handler.take().unwrap_or_else(default_handler::<Self>);
63 handler.replace(Box::new(move |event| {
64 prev(event);
65 f(event)
66 }));
67 })
68 }
69}
70impl<T: sealed::Event + 'static> EventExt for T {}
71
72macro_rules! impl_wifi_event {
73 ($newtype:ident) => {
75 #[derive(Copy, Clone)]
77 pub struct $newtype;
78 impl sealed::Event for $newtype {
79 unsafe fn from_raw_event_data(_: *mut crate::binary::c_types::c_void) -> Self {
80 Self
81 }
82 fn handler() -> &'static Locked<Option<Box<Handler<Self>>>> {
83 static HANDLE: Locked<Option<Box<Handler<$newtype>>>> = Locked::new(None);
84 &HANDLE
85 }
86 }
87 };
88 ($newtype:ident, $data:ident) => {
90 pub use esp_wifi_sys::include::$data;
91 #[derive(Copy, Clone)]
93 pub struct $newtype(pub $data);
94 impl sealed::Event for $newtype {
95 unsafe fn from_raw_event_data(ptr: *mut crate::binary::c_types::c_void) -> Self {
96 Self(unsafe { *ptr.cast() })
97 }
98 fn handler() -> &'static Locked<Option<Box<Handler<Self>>>> {
99 static HANDLE: Locked<Option<Box<Handler<$newtype>>>> = Locked::new(None);
100 &HANDLE
101 }
102 }
103 };
104}
105
106impl_wifi_event!(WifiReady);
107impl_wifi_event!(ScanDone, wifi_event_sta_scan_done_t);
108impl_wifi_event!(StaStart);
109impl_wifi_event!(StaStop);
110impl_wifi_event!(StaConnected, wifi_event_sta_connected_t);
111impl_wifi_event!(StaDisconnected, wifi_event_sta_disconnected_t);
112impl_wifi_event!(StaAuthmodeChange, wifi_event_sta_authmode_change_t);
113impl_wifi_event!(StaWpsErSuccess, wifi_event_sta_wps_er_success_t);
114impl_wifi_event!(StaWpsErFailed);
115impl_wifi_event!(StaWpsErTimeout);
116impl_wifi_event!(StaWpsErPin, wifi_event_sta_wps_er_pin_t);
117impl_wifi_event!(StaWpsErPbcOverlap);
118impl_wifi_event!(ApStart);
119impl_wifi_event!(ApStop);
120impl_wifi_event!(ApStaconnected, wifi_event_ap_staconnected_t);
121impl_wifi_event!(ApStadisconnected, wifi_event_ap_stadisconnected_t);
122impl_wifi_event!(ApProbereqrecved, wifi_event_ap_probe_req_rx_t);
123impl_wifi_event!(FtmReport, wifi_event_ftm_report_t);
124impl_wifi_event!(StaBssRssiLow, wifi_event_bss_rssi_low_t);
125impl_wifi_event!(ActionTxStatus, wifi_event_action_tx_status_t);
126impl_wifi_event!(RocDone, wifi_event_roc_done_t);
127impl_wifi_event!(StaBeaconTimeout);
128impl_wifi_event!(ConnectionlessModuleWakeIntervalStart);
129impl_wifi_event!(ApWpsRgSuccess, wifi_event_ap_wps_rg_success_t);
130impl_wifi_event!(ApWpsRgFailed, wifi_event_ap_wps_rg_fail_reason_t);
131impl_wifi_event!(ApWpsRgTimeout);
132impl_wifi_event!(ApWpsRgPin, wifi_event_ap_wps_rg_pin_t);
133impl_wifi_event!(ApWpsRgPbcOverlap);
134cfg_if::cfg_if! {
135 if #[cfg(wifi6)] {
136 impl_wifi_event!(ItwtSetup, wifi_event_sta_itwt_setup_t);
137 impl_wifi_event!(ItwtTeardown, wifi_event_sta_itwt_teardown_t);
138 impl_wifi_event!(ItwtProbe, wifi_event_sta_itwt_probe_t);
139 impl_wifi_event!(ItwtSuspend, wifi_event_sta_itwt_suspend_t);
140 impl_wifi_event!(TwtWakeup);
141 impl_wifi_event!(BtwtSetup, wifi_event_sta_btwt_setup_t);
142 impl_wifi_event!(BtwtTeardown, wifi_event_sta_btwt_teardown_t);
143 } else {
144 impl_wifi_event!(ItwtSetup);
145 impl_wifi_event!(ItwtTeardown);
146 impl_wifi_event!(ItwtProbe);
147 impl_wifi_event!(ItwtSuspend);
148 impl_wifi_event!(TwtWakeup);
149 impl_wifi_event!(BtwtSetup);
150 impl_wifi_event!(BtwtTeardown);
151 }
152}
153impl_wifi_event!(NanStarted);
154impl_wifi_event!(NanStopped);
155impl_wifi_event!(NanSvcMatch, wifi_event_nan_svc_match_t);
156impl_wifi_event!(NanReplied, wifi_event_nan_replied_t);
157impl_wifi_event!(NanReceive, wifi_event_nan_receive_t);
158impl_wifi_event!(NdpIndication, wifi_event_ndp_indication_t);
159impl_wifi_event!(NdpConfirm, wifi_event_ndp_confirm_t);
160impl_wifi_event!(NdpTerminated, wifi_event_ndp_terminated_t);
161impl_wifi_event!(HomeChannelChange, wifi_event_home_channel_change_t);
162impl_wifi_event!(StaNeighborRep, wifi_event_neighbor_report_t);
163
164pub fn handle<Event: EventExt>(event_data: &Event) -> bool {
166 Event::handler().with(|handler| {
167 if let Some(handler) = handler {
168 handler(event_data);
169 true
170 } else {
171 false
172 }
173 })
174}
175
176pub(crate) unsafe fn handle_raw<Event: EventExt>(
180 event_data: *mut crate::binary::c_types::c_void,
181 event_data_size: usize,
182) -> bool {
183 debug_assert_eq!(
184 event_data_size,
185 core::mem::size_of::<Event>(),
186 "wrong size event data"
187 );
188
189 handle::<Event>(unsafe { &Event::from_raw_event_data(event_data) })
190}
191
192#[rustfmt::skip]
196pub(crate) unsafe fn dispatch_event_handler(
197 event: WifiEvent,
198 event_data: *mut crate::binary::c_types::c_void,
199 event_data_size: usize,
200) -> bool {
201 match event {
202 WifiEvent::WifiReady => {
203 handle_raw::<WifiReady>(event_data, event_data_size)
204 }
205 WifiEvent::ScanDone => {
206 handle_raw::<ScanDone>(event_data, event_data_size)
207 }
208 WifiEvent::StaStart => {
209 handle_raw::<StaStart>(event_data, event_data_size)
210 }
211 WifiEvent::StaStop => {
212 handle_raw::<StaStop>(event_data, event_data_size)
213 }
214 WifiEvent::StaConnected => {
215 handle_raw::<StaConnected>(event_data, event_data_size)
216 }
217 WifiEvent::StaDisconnected => {
218 handle_raw::<StaDisconnected>(event_data, event_data_size)
219 }
220 WifiEvent::StaAuthmodeChange => {
221 handle_raw::<StaAuthmodeChange>(event_data, event_data_size)
222 }
223 WifiEvent::StaWpsErSuccess => {
224 handle_raw::<StaWpsErSuccess>(event_data, event_data_size)
225 }
226 WifiEvent::StaWpsErFailed => {
227 handle_raw::<StaWpsErFailed>(event_data, event_data_size)
228 }
229 WifiEvent::StaWpsErTimeout => {
230 handle_raw::<StaWpsErTimeout>(event_data, event_data_size)
231 }
232 WifiEvent::StaWpsErPin => {
233 handle_raw::<StaWpsErPin>(event_data, event_data_size)
234 }
235 WifiEvent::StaWpsErPbcOverlap => {
236 handle_raw::<StaWpsErPbcOverlap>(event_data, event_data_size)
237 }
238 WifiEvent::ApStart => {
239 handle_raw::<ApStart>(event_data, event_data_size)
240 }
241 WifiEvent::ApStop => {
242 handle_raw::<ApStop>(event_data, event_data_size)
243 }
244 WifiEvent::ApStaconnected => {
245 handle_raw::<ApStaconnected>(event_data, event_data_size)
246 }
247 WifiEvent::ApStadisconnected => {
248 handle_raw::<ApStadisconnected>(event_data, event_data_size)
249 }
250 WifiEvent::ApProbereqrecved => {
251 handle_raw::<ApProbereqrecved>(event_data, event_data_size)
252 }
253 WifiEvent::FtmReport => {
254 handle_raw::<FtmReport>(event_data, event_data_size)
255 }
256 WifiEvent::StaBssRssiLow => {
257 handle_raw::<StaBssRssiLow>(event_data, event_data_size)
258 }
259 WifiEvent::ActionTxStatus => {
260 handle_raw::<ActionTxStatus>(event_data, event_data_size)
261 }
262 WifiEvent::RocDone => {
263 handle_raw::<RocDone>(event_data, event_data_size)
264 }
265 WifiEvent::StaBeaconTimeout => {
266 handle_raw::<StaBeaconTimeout>(event_data, event_data_size)
267 }
268 WifiEvent::ConnectionlessModuleWakeIntervalStart => {
269 handle_raw::<ConnectionlessModuleWakeIntervalStart>(event_data, event_data_size)
270 }
271 WifiEvent::ApWpsRgSuccess => {
272 handle_raw::<ApWpsRgSuccess>(event_data, event_data_size)
273 }
274 WifiEvent::ApWpsRgFailed => {
275 handle_raw::<ApWpsRgFailed>(event_data, event_data_size)
276 }
277 WifiEvent::ApWpsRgTimeout => {
278 handle_raw::<ApWpsRgTimeout>(event_data, event_data_size)
279 }
280 WifiEvent::ApWpsRgPin => {
281 handle_raw::<ApWpsRgPin>(event_data, event_data_size)
282 }
283 WifiEvent::ApWpsRgPbcOverlap => {
284 handle_raw::<ApWpsRgPbcOverlap>(event_data, event_data_size)
285 }
286 WifiEvent::ItwtSetup => {
287 handle_raw::<ItwtSetup>(event_data, event_data_size)
288 }
289 WifiEvent::ItwtTeardown => {
290 handle_raw::<ItwtTeardown>(event_data, event_data_size)
291 }
292 WifiEvent::ItwtProbe => {
293 handle_raw::<ItwtProbe>(event_data, event_data_size)
294 }
295 WifiEvent::ItwtSuspend => {
296 handle_raw::<ItwtSuspend>(event_data, event_data_size)
297 }
298 WifiEvent::TwtWakeup => {
299 handle_raw::<TwtWakeup>(event_data, event_data_size)
300 }
301 WifiEvent::BtwtSetup => {
302 handle_raw::<BtwtSetup>(event_data, event_data_size)
303 }
304 WifiEvent::BtwtTeardown => {
305 handle_raw::<BtwtTeardown>(event_data, event_data_size)
306 }
307 WifiEvent::NanStarted => {
308 handle_raw::<NanStarted>(event_data, event_data_size)
309 }
310 WifiEvent::NanStopped => {
311 handle_raw::<NanStopped>(event_data, event_data_size)
312 }
313 WifiEvent::NanSvcMatch => {
314 handle_raw::<NanSvcMatch>(event_data, event_data_size)
315 }
316 WifiEvent::NanReplied => {
317 handle_raw::<NanReplied>(event_data, event_data_size)
318 }
319 WifiEvent::NanReceive => {
320 handle_raw::<NanReceive>(event_data, event_data_size)
321 }
322 WifiEvent::NdpIndication => {
323 handle_raw::<NdpIndication>(event_data, event_data_size)
324 }
325 WifiEvent::NdpConfirm => {
326 handle_raw::<NdpConfirm>(event_data, event_data_size)
327 }
328 WifiEvent::NdpTerminated => {
329 handle_raw::<NdpTerminated>(event_data, event_data_size)
330 }
331 WifiEvent::HomeChannelChange => {
332 handle_raw::<HomeChannelChange>(event_data, event_data_size)
333 }
334 WifiEvent::StaNeighborRep => {
335 handle_raw::<StaNeighborRep>(event_data, event_data_size)
336 }
337 }
338}