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(wifi_has_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 let event = unsafe { Event::from_raw_event_data(event_data) };
190 handle::<Event>(&event)
191}
192
193#[rustfmt::skip]
197pub(crate) unsafe fn dispatch_event_handler(
198 event: WifiEvent,
199 event_data: *mut crate::binary::c_types::c_void,
200 event_data_size: usize,
201) -> bool { unsafe {
202 match event {
203 WifiEvent::WifiReady => {
204 handle_raw::<WifiReady>(event_data, event_data_size)
205 }
206 WifiEvent::ScanDone => {
207 handle_raw::<ScanDone>(event_data, event_data_size)
208 }
209 WifiEvent::StaStart => {
210 handle_raw::<StaStart>(event_data, event_data_size)
211 }
212 WifiEvent::StaStop => {
213 handle_raw::<StaStop>(event_data, event_data_size)
214 }
215 WifiEvent::StaConnected => {
216 handle_raw::<StaConnected>(event_data, event_data_size)
217 }
218 WifiEvent::StaDisconnected => {
219 handle_raw::<StaDisconnected>(event_data, event_data_size)
220 }
221 WifiEvent::StaAuthmodeChange => {
222 handle_raw::<StaAuthmodeChange>(event_data, event_data_size)
223 }
224 WifiEvent::StaWpsErSuccess => {
225 handle_raw::<StaWpsErSuccess>(event_data, event_data_size)
226 }
227 WifiEvent::StaWpsErFailed => {
228 handle_raw::<StaWpsErFailed>(event_data, event_data_size)
229 }
230 WifiEvent::StaWpsErTimeout => {
231 handle_raw::<StaWpsErTimeout>(event_data, event_data_size)
232 }
233 WifiEvent::StaWpsErPin => {
234 handle_raw::<StaWpsErPin>(event_data, event_data_size)
235 }
236 WifiEvent::StaWpsErPbcOverlap => {
237 handle_raw::<StaWpsErPbcOverlap>(event_data, event_data_size)
238 }
239 WifiEvent::ApStart => {
240 handle_raw::<ApStart>(event_data, event_data_size)
241 }
242 WifiEvent::ApStop => {
243 handle_raw::<ApStop>(event_data, event_data_size)
244 }
245 WifiEvent::ApStaconnected => {
246 handle_raw::<ApStaconnected>(event_data, event_data_size)
247 }
248 WifiEvent::ApStadisconnected => {
249 handle_raw::<ApStadisconnected>(event_data, event_data_size)
250 }
251 WifiEvent::ApProbereqrecved => {
252 handle_raw::<ApProbereqrecved>(event_data, event_data_size)
253 }
254 WifiEvent::FtmReport => {
255 handle_raw::<FtmReport>(event_data, event_data_size)
256 }
257 WifiEvent::StaBssRssiLow => {
258 handle_raw::<StaBssRssiLow>(event_data, event_data_size)
259 }
260 WifiEvent::ActionTxStatus => {
261 handle_raw::<ActionTxStatus>(event_data, event_data_size)
262 }
263 WifiEvent::RocDone => {
264 handle_raw::<RocDone>(event_data, event_data_size)
265 }
266 WifiEvent::StaBeaconTimeout => {
267 handle_raw::<StaBeaconTimeout>(event_data, event_data_size)
268 }
269 WifiEvent::ConnectionlessModuleWakeIntervalStart => {
270 handle_raw::<ConnectionlessModuleWakeIntervalStart>(event_data, event_data_size)
271 }
272 WifiEvent::ApWpsRgSuccess => {
273 handle_raw::<ApWpsRgSuccess>(event_data, event_data_size)
274 }
275 WifiEvent::ApWpsRgFailed => {
276 handle_raw::<ApWpsRgFailed>(event_data, event_data_size)
277 }
278 WifiEvent::ApWpsRgTimeout => {
279 handle_raw::<ApWpsRgTimeout>(event_data, event_data_size)
280 }
281 WifiEvent::ApWpsRgPin => {
282 handle_raw::<ApWpsRgPin>(event_data, event_data_size)
283 }
284 WifiEvent::ApWpsRgPbcOverlap => {
285 handle_raw::<ApWpsRgPbcOverlap>(event_data, event_data_size)
286 }
287 WifiEvent::ItwtSetup => {
288 handle_raw::<ItwtSetup>(event_data, event_data_size)
289 }
290 WifiEvent::ItwtTeardown => {
291 handle_raw::<ItwtTeardown>(event_data, event_data_size)
292 }
293 WifiEvent::ItwtProbe => {
294 handle_raw::<ItwtProbe>(event_data, event_data_size)
295 }
296 WifiEvent::ItwtSuspend => {
297 handle_raw::<ItwtSuspend>(event_data, event_data_size)
298 }
299 WifiEvent::TwtWakeup => {
300 handle_raw::<TwtWakeup>(event_data, event_data_size)
301 }
302 WifiEvent::BtwtSetup => {
303 handle_raw::<BtwtSetup>(event_data, event_data_size)
304 }
305 WifiEvent::BtwtTeardown => {
306 handle_raw::<BtwtTeardown>(event_data, event_data_size)
307 }
308 WifiEvent::NanStarted => {
309 handle_raw::<NanStarted>(event_data, event_data_size)
310 }
311 WifiEvent::NanStopped => {
312 handle_raw::<NanStopped>(event_data, event_data_size)
313 }
314 WifiEvent::NanSvcMatch => {
315 handle_raw::<NanSvcMatch>(event_data, event_data_size)
316 }
317 WifiEvent::NanReplied => {
318 handle_raw::<NanReplied>(event_data, event_data_size)
319 }
320 WifiEvent::NanReceive => {
321 handle_raw::<NanReceive>(event_data, event_data_size)
322 }
323 WifiEvent::NdpIndication => {
324 handle_raw::<NdpIndication>(event_data, event_data_size)
325 }
326 WifiEvent::NdpConfirm => {
327 handle_raw::<NdpConfirm>(event_data, event_data_size)
328 }
329 WifiEvent::NdpTerminated => {
330 handle_raw::<NdpTerminated>(event_data, event_data_size)
331 }
332 WifiEvent::HomeChannelChange => {
333 handle_raw::<HomeChannelChange>(event_data, event_data_size)
334 }
335 WifiEvent::StaNeighborRep => {
336 handle_raw::<StaNeighborRep>(event_data, event_data_size)
337 }
338 }
339}}