1use anyhow::{format_err, Context};
6use fidl::endpoints::ClientEnd;
7use {
8 fidl_fuchsia_wlan_common as fidl_common, fidl_fuchsia_wlan_fullmac as fidl_fullmac,
9 fidl_fuchsia_wlan_mlme as fidl_mlme, fidl_fuchsia_wlan_stats as fidl_stats,
10};
11
12pub trait DeviceOps {
16 fn init(
17 &mut self,
18 fullmac_ifc_client_end: ClientEnd<fidl_fullmac::WlanFullmacImplIfcMarker>,
19 ) -> Result<fidl::Channel, zx::Status>;
20 fn query_device_info(&self) -> anyhow::Result<fidl_fullmac::WlanFullmacImplQueryResponse>;
21 fn query_security_support(&self) -> anyhow::Result<fidl_common::SecuritySupport>;
22 fn query_spectrum_management_support(
23 &self,
24 ) -> anyhow::Result<fidl_common::SpectrumManagementSupport>;
25 fn query_telemetry_support(&self) -> anyhow::Result<Result<fidl_stats::TelemetrySupport, i32>>;
26 fn start_scan(&self, req: fidl_fullmac::WlanFullmacImplStartScanRequest) -> anyhow::Result<()>;
27 fn connect(&self, req: fidl_fullmac::WlanFullmacImplConnectRequest) -> anyhow::Result<()>;
28 fn reconnect(&self, req: fidl_fullmac::WlanFullmacImplReconnectRequest) -> anyhow::Result<()>;
29 fn roam(&self, req: fidl_fullmac::WlanFullmacImplRoamRequest) -> anyhow::Result<()>;
30 fn auth_resp(&self, resp: fidl_fullmac::WlanFullmacImplAuthRespRequest) -> anyhow::Result<()>;
31 fn deauth(&self, req: fidl_fullmac::WlanFullmacImplDeauthRequest) -> anyhow::Result<()>;
32 fn assoc_resp(&self, resp: fidl_fullmac::WlanFullmacImplAssocRespRequest)
33 -> anyhow::Result<()>;
34 fn disassoc(&self, req: fidl_fullmac::WlanFullmacImplDisassocRequest) -> anyhow::Result<()>;
35 fn start_bss(&self, req: fidl_fullmac::WlanFullmacImplStartBssRequest) -> anyhow::Result<()>;
36 fn stop_bss(&self, req: fidl_fullmac::WlanFullmacImplStopBssRequest) -> anyhow::Result<()>;
37 fn set_keys(
38 &self,
39 req: fidl_fullmac::WlanFullmacImplSetKeysRequest,
40 ) -> anyhow::Result<fidl_fullmac::WlanFullmacSetKeysResp>;
41 fn eapol_tx(&self, req: fidl_fullmac::WlanFullmacImplEapolTxRequest) -> anyhow::Result<()>;
42 fn get_iface_stats(&self) -> anyhow::Result<fidl_mlme::GetIfaceStatsResponse>;
43 fn get_iface_histogram_stats(
44 &self,
45 ) -> anyhow::Result<fidl_mlme::GetIfaceHistogramStatsResponse>;
46 fn sae_handshake_resp(
47 &self,
48 resp: fidl_fullmac::WlanFullmacImplSaeHandshakeRespRequest,
49 ) -> anyhow::Result<()>;
50 fn sae_frame_tx(&self, frame: fidl_fullmac::SaeFrame) -> anyhow::Result<()>;
51 fn wmm_status_req(&self) -> anyhow::Result<()>;
52 fn on_link_state_changed(
53 &self,
54 req: fidl_fullmac::WlanFullmacImplOnLinkStateChangedRequest,
55 ) -> anyhow::Result<()>;
56}
57
58pub struct FullmacDevice {
59 fullmac_impl_sync_proxy: fidl_fullmac::WlanFullmacImpl_SynchronousProxy,
60}
61
62impl FullmacDevice {
65 pub fn new(
66 fullmac_impl_sync_proxy: fidl_fullmac::WlanFullmacImpl_SynchronousProxy,
67 ) -> FullmacDevice {
68 FullmacDevice { fullmac_impl_sync_proxy }
69 }
70}
71
72impl DeviceOps for FullmacDevice {
73 fn init(
74 &mut self,
75 fullmac_ifc_client_end: ClientEnd<fidl_fullmac::WlanFullmacImplIfcMarker>,
76 ) -> Result<fidl::Channel, zx::Status> {
77 let req = fidl_fullmac::WlanFullmacImplInitRequest {
78 ifc: Some(fullmac_ifc_client_end),
79 ..Default::default()
80 };
81 let resp = self
82 .fullmac_impl_sync_proxy
83 .init(req, zx::MonotonicInstant::INFINITE)
84 .map_err(|e| {
85 log::error!("FIDL error on Start: {}", e);
86 zx::Status::INTERNAL
87 })?
88 .map_err(|e| zx::Status::from_raw(e))?;
89
90 resp.sme_channel.ok_or(zx::Status::INVALID_ARGS)
91 }
92
93 fn query_device_info(&self) -> anyhow::Result<fidl_fullmac::WlanFullmacImplQueryResponse> {
94 self.fullmac_impl_sync_proxy
95 .query(zx::MonotonicInstant::INFINITE)
96 .context("FIDL error on QueryDeviceInfo")?
97 .map_err(|e| format_err!("Driver returned error on QueryDeviceInfo: {}", e))
98 }
99
100 fn query_security_support(&self) -> anyhow::Result<fidl_common::SecuritySupport> {
101 self.fullmac_impl_sync_proxy
102 .query_security_support(zx::MonotonicInstant::INFINITE)
103 .context("FIDL error on QuerySecuritySupport")?
104 .map_err(|e| format_err!("Driver returned error on QuerySecuritySupport: {}", e))
105 }
106
107 fn query_spectrum_management_support(
108 &self,
109 ) -> anyhow::Result<fidl_common::SpectrumManagementSupport> {
110 self.fullmac_impl_sync_proxy
111 .query_spectrum_management_support(zx::MonotonicInstant::INFINITE)
112 .context("FIDL error on QuerySpectrumManagementSupport")?
113 .map_err(|e| {
114 format_err!("Driver returned error on QuerySpectrumManagementSupport: {}", e)
115 })
116 }
117
118 fn query_telemetry_support(&self) -> anyhow::Result<Result<fidl_stats::TelemetrySupport, i32>> {
119 self.fullmac_impl_sync_proxy
120 .query_telemetry_support(zx::MonotonicInstant::INFINITE)
121 .context("FIDL error on QueryTelemetrySupport")
122 }
123
124 fn start_scan(&self, req: fidl_fullmac::WlanFullmacImplStartScanRequest) -> anyhow::Result<()> {
125 self.fullmac_impl_sync_proxy
126 .start_scan(&req, zx::MonotonicInstant::INFINITE)
127 .context("FIDL error on StartScan")
128 }
129 fn connect(&self, req: fidl_fullmac::WlanFullmacImplConnectRequest) -> anyhow::Result<()> {
130 self.fullmac_impl_sync_proxy
131 .connect(&req, zx::MonotonicInstant::INFINITE)
132 .context("FIDL error on Connect")
133 }
134 fn reconnect(&self, req: fidl_fullmac::WlanFullmacImplReconnectRequest) -> anyhow::Result<()> {
135 self.fullmac_impl_sync_proxy
136 .reconnect(&req, zx::MonotonicInstant::INFINITE)
137 .context("FIDL error on Reconnect")
138 }
139 fn roam(&self, req: fidl_fullmac::WlanFullmacImplRoamRequest) -> anyhow::Result<()> {
140 self.fullmac_impl_sync_proxy
141 .roam(&req, zx::MonotonicInstant::INFINITE)
142 .context("FIDL error on Roam")
143 }
144 fn auth_resp(&self, resp: fidl_fullmac::WlanFullmacImplAuthRespRequest) -> anyhow::Result<()> {
145 self.fullmac_impl_sync_proxy
146 .auth_resp(&resp, zx::MonotonicInstant::INFINITE)
147 .context("FIDL error on AuthResp")
148 }
149 fn deauth(&self, req: fidl_fullmac::WlanFullmacImplDeauthRequest) -> anyhow::Result<()> {
150 self.fullmac_impl_sync_proxy
151 .deauth(&req, zx::MonotonicInstant::INFINITE)
152 .context("FIDL error on Deauth")
153 }
154 fn assoc_resp(
155 &self,
156 resp: fidl_fullmac::WlanFullmacImplAssocRespRequest,
157 ) -> anyhow::Result<()> {
158 self.fullmac_impl_sync_proxy
159 .assoc_resp(&resp, zx::MonotonicInstant::INFINITE)
160 .context("FIDL error on AssocResp")
161 }
162 fn disassoc(&self, req: fidl_fullmac::WlanFullmacImplDisassocRequest) -> anyhow::Result<()> {
163 self.fullmac_impl_sync_proxy
164 .disassoc(&req, zx::MonotonicInstant::INFINITE)
165 .context("FIDL error on Disassoc")
166 }
167 fn start_bss(&self, req: fidl_fullmac::WlanFullmacImplStartBssRequest) -> anyhow::Result<()> {
168 self.fullmac_impl_sync_proxy
169 .start_bss(&req, zx::MonotonicInstant::INFINITE)
170 .context("FIDL error on StartBss")
171 }
172 fn stop_bss(&self, req: fidl_fullmac::WlanFullmacImplStopBssRequest) -> anyhow::Result<()> {
173 self.fullmac_impl_sync_proxy
174 .stop_bss(&req, zx::MonotonicInstant::INFINITE)
175 .context("FIDL error on StopBss")
176 }
177 fn set_keys(
178 &self,
179 req: fidl_fullmac::WlanFullmacImplSetKeysRequest,
180 ) -> anyhow::Result<fidl_fullmac::WlanFullmacSetKeysResp> {
181 self.fullmac_impl_sync_proxy
182 .set_keys(&req, zx::MonotonicInstant::INFINITE)
183 .context("FIDL error on SetKeysReq")
184 }
185 fn eapol_tx(&self, req: fidl_fullmac::WlanFullmacImplEapolTxRequest) -> anyhow::Result<()> {
186 self.fullmac_impl_sync_proxy
187 .eapol_tx(&req, zx::MonotonicInstant::INFINITE)
188 .context("FIDL error on EapolTx")
189 }
190 fn get_iface_stats(&self) -> anyhow::Result<fidl_mlme::GetIfaceStatsResponse> {
191 match self
192 .fullmac_impl_sync_proxy
193 .get_iface_stats(zx::MonotonicInstant::INFINITE)
194 .context("FIDL error on GetIfaceStats")?
195 {
196 Ok(stats) => Ok(fidl_mlme::GetIfaceStatsResponse::Stats(stats)),
197 Err(e) => Ok(fidl_mlme::GetIfaceStatsResponse::ErrorStatus(e)),
198 }
199 }
200 fn get_iface_histogram_stats(
201 &self,
202 ) -> anyhow::Result<fidl_mlme::GetIfaceHistogramStatsResponse> {
203 match self
204 .fullmac_impl_sync_proxy
205 .get_iface_histogram_stats(zx::MonotonicInstant::INFINITE)
206 .context("FIDL error on GetIfaceHistogramStats")?
207 {
208 Ok(stats) => Ok(fidl_mlme::GetIfaceHistogramStatsResponse::Stats(stats)),
209 Err(e) => Ok(fidl_mlme::GetIfaceHistogramStatsResponse::ErrorStatus(e)),
210 }
211 }
212 fn sae_handshake_resp(
213 &self,
214 resp: fidl_fullmac::WlanFullmacImplSaeHandshakeRespRequest,
215 ) -> anyhow::Result<()> {
216 self.fullmac_impl_sync_proxy
217 .sae_handshake_resp(&resp, zx::MonotonicInstant::INFINITE)
218 .context("FIDL error on SaeHandshakeResp")
219 }
220 fn sae_frame_tx(&self, frame: fidl_fullmac::SaeFrame) -> anyhow::Result<()> {
221 self.fullmac_impl_sync_proxy
222 .sae_frame_tx(&frame, zx::MonotonicInstant::INFINITE)
223 .context("FIDL error on SaeFrameTx")
224 }
225 fn wmm_status_req(&self) -> anyhow::Result<()> {
226 self.fullmac_impl_sync_proxy
227 .wmm_status_req(zx::MonotonicInstant::INFINITE)
228 .context("FIDL error on WmmStatusReq")
229 }
230 fn on_link_state_changed(
231 &self,
232 req: fidl_fullmac::WlanFullmacImplOnLinkStateChangedRequest,
233 ) -> anyhow::Result<()> {
234 self.fullmac_impl_sync_proxy
235 .on_link_state_changed(&req, zx::MonotonicInstant::INFINITE)
236 .context("FIDL error on OnLinkStateChanged")
237 }
238}
239
240#[cfg(test)]
241pub mod test_utils {
242 use super::*;
243 use fidl_fuchsia_wlan_sme as fidl_sme;
244 use futures::channel::mpsc;
245 use std::sync::{Arc, Mutex};
246 use wlan_common::sink::UnboundedSink;
247
248 #[derive(Debug)]
249 pub enum DriverCall {
250 StartScan { req: fidl_fullmac::WlanFullmacImplStartScanRequest },
251 ConnectReq { req: fidl_fullmac::WlanFullmacImplConnectRequest },
252 ReconnectReq { req: fidl_fullmac::WlanFullmacImplReconnectRequest },
253 RoamReq { req: fidl_fullmac::WlanFullmacImplRoamRequest },
254 AuthResp { resp: fidl_fullmac::WlanFullmacImplAuthRespRequest },
255 DeauthReq { req: fidl_fullmac::WlanFullmacImplDeauthRequest },
256 AssocResp { resp: fidl_fullmac::WlanFullmacImplAssocRespRequest },
257 Disassoc { req: fidl_fullmac::WlanFullmacImplDisassocRequest },
258 StartBss { req: fidl_fullmac::WlanFullmacImplStartBssRequest },
259 StopBss { req: fidl_fullmac::WlanFullmacImplStopBssRequest },
260 SetKeys { req: fidl_fullmac::WlanFullmacImplSetKeysRequest },
261 EapolTx { req: fidl_fullmac::WlanFullmacImplEapolTxRequest },
262 QueryTelemetrySupport,
263 GetIfaceStats,
264 GetIfaceHistogramStats,
265 SaeHandshakeResp { resp: fidl_fullmac::WlanFullmacImplSaeHandshakeRespRequest },
266 SaeFrameTx { frame: fidl_fullmac::SaeFrame },
267 WmmStatusReq,
268 OnLinkStateChanged { req: fidl_fullmac::WlanFullmacImplOnLinkStateChangedRequest },
269 }
270
271 pub struct FakeFullmacDeviceMocks {
272 pub start_fn_status_mock: Option<zx::sys::zx_status_t>,
273
274 pub query_device_info_mock: Option<fidl_fullmac::WlanFullmacImplQueryResponse>,
280 pub query_security_support_mock: Option<fidl_common::SecuritySupport>,
281 pub query_spectrum_management_support_mock: Option<fidl_common::SpectrumManagementSupport>,
282 pub query_telemetry_support_mock: Option<Result<fidl_stats::TelemetrySupport, i32>>,
283
284 pub set_keys_resp_mock: Option<fidl_fullmac::WlanFullmacSetKeysResp>,
285 pub get_iface_stats_mock: Option<fidl_mlme::GetIfaceStatsResponse>,
286 pub get_iface_histogram_stats_mock: Option<fidl_mlme::GetIfaceHistogramStatsResponse>,
287
288 pub fullmac_ifc_client_end: Option<ClientEnd<fidl_fullmac::WlanFullmacImplIfcMarker>>,
289 }
290
291 unsafe impl Send for FakeFullmacDevice {}
292 pub struct FakeFullmacDevice {
293 pub usme_bootstrap_client_end:
294 Option<fidl::endpoints::ClientEnd<fidl_sme::UsmeBootstrapMarker>>,
295 pub usme_bootstrap_server_end:
296 Option<fidl::endpoints::ServerEnd<fidl_sme::UsmeBootstrapMarker>>,
297 driver_call_sender: UnboundedSink<DriverCall>,
298
299 pub mocks: Arc<Mutex<FakeFullmacDeviceMocks>>,
303 }
304
305 impl FakeFullmacDevice {
306 pub fn new() -> (Self, mpsc::UnboundedReceiver<DriverCall>) {
307 let (usme_bootstrap_client_end, usme_bootstrap_server_end) =
309 fidl::endpoints::create_endpoints::<fidl_sme::UsmeBootstrapMarker>();
310
311 let (driver_call_sender, driver_call_receiver) = mpsc::unbounded();
312
313 let device = Self {
314 usme_bootstrap_client_end: Some(usme_bootstrap_client_end),
315 usme_bootstrap_server_end: Some(usme_bootstrap_server_end),
316 driver_call_sender: UnboundedSink::new(driver_call_sender),
317 mocks: Arc::new(Mutex::new(FakeFullmacDeviceMocks {
318 fullmac_ifc_client_end: None,
319 start_fn_status_mock: None,
320 query_device_info_mock: Some(fidl_fullmac::WlanFullmacImplQueryResponse {
321 sta_addr: Some([0u8; 6]),
322 role: Some(fidl_common::WlanMacRole::Client),
323 band_caps: Some(vec![]),
324 ..Default::default()
325 }),
326 query_security_support_mock: Some(fidl_common::SecuritySupport {
327 sae: fidl_common::SaeFeature {
328 driver_handler_supported: false,
329 sme_handler_supported: true,
330 },
331 mfp: fidl_common::MfpFeature { supported: false },
332 }),
333 query_spectrum_management_support_mock: Some(
334 fidl_common::SpectrumManagementSupport {
335 dfs: fidl_common::DfsFeature { supported: false },
336 },
337 ),
338 query_telemetry_support_mock: Some(Ok(fidl_stats::TelemetrySupport {
339 ..Default::default()
340 })),
341 set_keys_resp_mock: None,
342 get_iface_stats_mock: None,
343 get_iface_histogram_stats_mock: None,
344 })),
345 };
346
347 (device, driver_call_receiver)
348 }
349 }
350
351 impl DeviceOps for FakeFullmacDevice {
352 fn init(
353 &mut self,
354 fullmac_ifc_client_end: ClientEnd<fidl_fullmac::WlanFullmacImplIfcMarker>,
355 ) -> Result<fidl::Channel, zx::Status> {
356 let mut mocks = self.mocks.lock().unwrap();
357
358 mocks.fullmac_ifc_client_end = Some(fullmac_ifc_client_end);
359 match mocks.start_fn_status_mock {
360 Some(status) => Err(zx::Status::from_raw(status)),
361
362 None => Ok(self.usme_bootstrap_server_end.take().unwrap().into_channel()),
364 }
365 }
366
367 fn query_device_info(&self) -> anyhow::Result<fidl_fullmac::WlanFullmacImplQueryResponse> {
368 self.mocks.lock().unwrap().query_device_info_mock.clone().ok_or(format_err!(""))
369 }
370
371 fn query_security_support(&self) -> anyhow::Result<fidl_common::SecuritySupport> {
372 self.mocks.lock().unwrap().query_security_support_mock.clone().ok_or(format_err!(""))
373 }
374
375 fn query_spectrum_management_support(
376 &self,
377 ) -> anyhow::Result<fidl_common::SpectrumManagementSupport> {
378 self.mocks
379 .lock()
380 .unwrap()
381 .query_spectrum_management_support_mock
382 .clone()
383 .ok_or(format_err!(""))
384 }
385
386 fn query_telemetry_support(
387 &self,
388 ) -> anyhow::Result<Result<fidl_stats::TelemetrySupport, i32>> {
389 self.driver_call_sender.send(DriverCall::QueryTelemetrySupport);
390 self.mocks.lock().unwrap().query_telemetry_support_mock.clone().ok_or(format_err!(""))
391 }
392
393 fn start_scan(
395 &self,
396 req: fidl_fullmac::WlanFullmacImplStartScanRequest,
397 ) -> anyhow::Result<()> {
398 self.driver_call_sender.send(DriverCall::StartScan { req });
399 Ok(())
400 }
401
402 fn connect(&self, req: fidl_fullmac::WlanFullmacImplConnectRequest) -> anyhow::Result<()> {
403 self.driver_call_sender.send(DriverCall::ConnectReq { req });
404 Ok(())
405 }
406 fn reconnect(
407 &self,
408 req: fidl_fullmac::WlanFullmacImplReconnectRequest,
409 ) -> anyhow::Result<()> {
410 self.driver_call_sender.send(DriverCall::ReconnectReq { req });
411 Ok(())
412 }
413 fn roam(&self, req: fidl_fullmac::WlanFullmacImplRoamRequest) -> anyhow::Result<()> {
414 self.driver_call_sender.send(DriverCall::RoamReq { req });
415 Ok(())
416 }
417 fn auth_resp(
418 &self,
419 resp: fidl_fullmac::WlanFullmacImplAuthRespRequest,
420 ) -> anyhow::Result<()> {
421 self.driver_call_sender.send(DriverCall::AuthResp { resp });
422 Ok(())
423 }
424 fn deauth(&self, req: fidl_fullmac::WlanFullmacImplDeauthRequest) -> anyhow::Result<()> {
425 self.driver_call_sender.send(DriverCall::DeauthReq { req });
426 Ok(())
427 }
428 fn assoc_resp(
429 &self,
430 resp: fidl_fullmac::WlanFullmacImplAssocRespRequest,
431 ) -> anyhow::Result<()> {
432 self.driver_call_sender.send(DriverCall::AssocResp { resp });
433 Ok(())
434 }
435 fn disassoc(
436 &self,
437 req: fidl_fullmac::WlanFullmacImplDisassocRequest,
438 ) -> anyhow::Result<()> {
439 self.driver_call_sender.send(DriverCall::Disassoc { req });
440 Ok(())
441 }
442 fn start_bss(
443 &self,
444 req: fidl_fullmac::WlanFullmacImplStartBssRequest,
445 ) -> anyhow::Result<()> {
446 self.driver_call_sender.send(DriverCall::StartBss { req });
447 Ok(())
448 }
449 fn stop_bss(&self, req: fidl_fullmac::WlanFullmacImplStopBssRequest) -> anyhow::Result<()> {
450 self.driver_call_sender.send(DriverCall::StopBss { req });
451 Ok(())
452 }
453 fn set_keys(
454 &self,
455 req: fidl_fullmac::WlanFullmacImplSetKeysRequest,
456 ) -> anyhow::Result<fidl_fullmac::WlanFullmacSetKeysResp> {
457 let num_keys = req.keylist.as_ref().unwrap().len();
458 self.driver_call_sender.send(DriverCall::SetKeys { req });
459 match &self.mocks.lock().unwrap().set_keys_resp_mock {
460 Some(resp) => Ok(resp.clone()),
461 None => {
462 Ok(fidl_fullmac::WlanFullmacSetKeysResp { statuslist: vec![0i32; num_keys] })
463 }
464 }
465 }
466 fn eapol_tx(&self, req: fidl_fullmac::WlanFullmacImplEapolTxRequest) -> anyhow::Result<()> {
467 self.driver_call_sender.send(DriverCall::EapolTx { req });
468 Ok(())
469 }
470 fn get_iface_stats(&self) -> anyhow::Result<fidl_mlme::GetIfaceStatsResponse> {
471 self.driver_call_sender.send(DriverCall::GetIfaceStats);
472 Ok(self.mocks.lock().unwrap().get_iface_stats_mock.clone().unwrap_or(
473 fidl_mlme::GetIfaceStatsResponse::ErrorStatus(zx::sys::ZX_ERR_NOT_SUPPORTED),
474 ))
475 }
476 fn get_iface_histogram_stats(
477 &self,
478 ) -> anyhow::Result<fidl_mlme::GetIfaceHistogramStatsResponse> {
479 self.driver_call_sender.send(DriverCall::GetIfaceHistogramStats);
480 Ok(self.mocks.lock().unwrap().get_iface_histogram_stats_mock.clone().unwrap_or(
481 fidl_mlme::GetIfaceHistogramStatsResponse::ErrorStatus(
482 zx::sys::ZX_ERR_NOT_SUPPORTED,
483 ),
484 ))
485 }
486 fn sae_handshake_resp(
487 &self,
488 resp: fidl_fullmac::WlanFullmacImplSaeHandshakeRespRequest,
489 ) -> anyhow::Result<()> {
490 self.driver_call_sender.send(DriverCall::SaeHandshakeResp { resp });
491 Ok(())
492 }
493 fn sae_frame_tx(&self, frame: fidl_fullmac::SaeFrame) -> anyhow::Result<()> {
494 self.driver_call_sender.send(DriverCall::SaeFrameTx { frame });
495 Ok(())
496 }
497 fn wmm_status_req(&self) -> anyhow::Result<()> {
498 self.driver_call_sender.send(DriverCall::WmmStatusReq);
499 Ok(())
500 }
501 fn on_link_state_changed(
502 &self,
503 req: fidl_fullmac::WlanFullmacImplOnLinkStateChangedRequest,
504 ) -> anyhow::Result<()> {
505 self.driver_call_sender.send(DriverCall::OnLinkStateChanged { req });
506 Ok(())
507 }
508 }
509}