wlan_fullmac_mlme/
lib.rs

1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Turn on additional lints that could lead to unexpected crashes in production code
6#![warn(clippy::indexing_slicing)]
7#![cfg_attr(test, allow(clippy::indexing_slicing))]
8#![warn(clippy::unwrap_used)]
9#![cfg_attr(test, allow(clippy::unwrap_used))]
10#![warn(clippy::expect_used)]
11#![cfg_attr(test, allow(clippy::expect_used))]
12#![warn(clippy::unreachable)]
13#![cfg_attr(test, allow(clippy::unreachable))]
14#![warn(clippy::unimplemented)]
15#![cfg_attr(test, allow(clippy::unimplemented))]
16
17mod convert;
18pub mod device;
19mod logger;
20mod mlme_main_loop;
21mod wlan_fullmac_impl_ifc_request_handler;
22
23use crate::convert::fullmac_to_mlme;
24use crate::device::DeviceOps;
25use crate::mlme_main_loop::create_mlme_main_loop;
26use anyhow::bail;
27use fuchsia_inspect::Inspector;
28use futures::StreamExt;
29use futures::channel::{mpsc, oneshot};
30use futures::future::BoxFuture;
31use log::{error, info, warn};
32use wlan_common::sink::UnboundedSink;
33use wlan_ffi_transport::completers::Completer;
34use wlan_sme::serve::create_sme;
35use {
36    fidl_fuchsia_wlan_common as fidl_common, fidl_fuchsia_wlan_internal as fidl_internal,
37    fidl_fuchsia_wlan_mlme as fidl_mlme, fidl_fuchsia_wlan_sme as fidl_sme,
38    fuchsia_async as fasync,
39};
40
41#[derive(thiserror::Error, Debug)]
42pub enum FullmacMlmeError {
43    #[error("device.start failed: {0}")]
44    DeviceStartFailed(zx::Status),
45    #[error("Failed to get usme bootstrap stream: {0}")]
46    FailedToGetUsmeBootstrapStream(fidl::Error),
47    #[error("USME bootstrap stream failed: {0}")]
48    UsmeBootstrapStreamFailed(fidl::Error),
49    #[error("USME bootstrap stream terminated")]
50    UsmeBootstrapStreamTerminated,
51    #[error("Failed to duplicate inspect VMO")]
52    FailedToDuplicateInspectVmo,
53    #[error("Failed to respond to usme bootstrap request: {0}")]
54    FailedToRespondToUsmeBootstrapRequest(fidl::Error),
55    #[error("Failed to get generic SME stream: {0}")]
56    FailedToGetGenericSmeStream(fidl::Error),
57    #[error("Invalid MAC implementation type: {0:?}")]
58    InvalidMacImplementationType(fidl_common::MacImplementationType),
59    #[error("Invalid data plane type: {0:?}")]
60    InvalidDataPlaneType(fidl_common::DataPlaneType),
61    #[error("Failed to query vendor driver: {0:?}")]
62    FailedToQueryVendorDriver(anyhow::Error),
63    #[error("Failed to convert query from vendor driver: {0:?}")]
64    FailedToConvertVendorDriverQuery(anyhow::Error),
65    #[error("Failed to create sme: {0}")]
66    FailedToCreateSme(anyhow::Error),
67    #[error("Failed to create WlanFullmacImplIfcRequestStream: {0}")]
68    FailedToCreateIfcRequestStream(fidl::Error),
69}
70
71#[derive(Debug)]
72struct FullmacDriverEventSink(pub UnboundedSink<FullmacDriverEvent>);
73
74#[derive(Debug)]
75enum FullmacDriverEvent {
76    Stop,
77    OnScanResult { result: fidl_mlme::ScanResult },
78    OnScanEnd { end: fidl_mlme::ScanEnd },
79    ConnectConf { resp: fidl_mlme::ConnectConfirm },
80    RoamConf { conf: fidl_mlme::RoamConfirm },
81    RoamStartInd { ind: fidl_mlme::RoamStartIndication },
82    RoamResultInd { ind: fidl_mlme::RoamResultIndication },
83    AuthInd { ind: fidl_mlme::AuthenticateIndication },
84    DeauthConf { resp: fidl_mlme::DeauthenticateConfirm },
85    DeauthInd { ind: fidl_mlme::DeauthenticateIndication },
86    AssocInd { ind: fidl_mlme::AssociateIndication },
87    DisassocConf { resp: fidl_mlme::DisassociateConfirm },
88    DisassocInd { ind: fidl_mlme::DisassociateIndication },
89    StartConf { resp: fidl_mlme::StartConfirm },
90    StopConf { resp: fidl_mlme::StopConfirm },
91    EapolConf { resp: fidl_mlme::EapolConfirm },
92    OnChannelSwitch { resp: fidl_internal::ChannelSwitchInfo },
93    SignalReport { ind: fidl_internal::SignalReportIndication },
94    EapolInd { ind: fidl_mlme::EapolIndication },
95    OnPmkAvailable { info: fidl_mlme::PmkInfo },
96    SaeHandshakeInd { ind: fidl_mlme::SaeHandshakeIndication },
97    SaeFrameRx { frame: fidl_mlme::SaeFrame },
98    OnWmmStatusResp { status: i32, resp: fidl_internal::WmmStatusResponse },
99}
100
101enum DriverState {
102    Running,
103    Stopping,
104}
105
106pub struct FullmacMlmeHandle {
107    driver_event_sender: mpsc::UnboundedSender<FullmacDriverEvent>,
108    mlme_loop_join_handle: Option<std::thread::JoinHandle<()>>,
109    stop_requested: bool,
110}
111
112impl FullmacMlmeHandle {
113    pub fn request_stop(&mut self) {
114        info!("Requesting MLME stop...");
115        if let Err(e) = self.driver_event_sender.unbounded_send(FullmacDriverEvent::Stop) {
116            error!("Cannot signal MLME event loop thread: {}", e);
117        } else {
118            // Only set this to true if sending the Stop event succeeded. Most likely, this means
119            // that the receiver was dropped and the MLME thread has already exited. But just in
120            // case sending can result in a different error, this will let us retry sending the
121            // Stop event in |Self::delete|. If it fails again, then we only emit another error
122            // log.
123            self.stop_requested = true;
124        }
125    }
126
127    pub fn delete(mut self) {
128        if !self.stop_requested {
129            warn!("Called delete on FullmacMlmeHandle before calling stop.");
130            self.request_stop()
131        }
132
133        match self.mlme_loop_join_handle.take() {
134            Some(join_handle) => {
135                if let Err(e) = join_handle.join() {
136                    error!("MLME event loop thread panicked: {:?}", e);
137                }
138            }
139            None => warn!("Called stop on already stopped MLME"),
140        }
141        info!("MLME main loop thread has shutdown.");
142    }
143}
144
145const INSPECT_VMO_SIZE_BYTES: usize = 1000 * 1024;
146
147/// Starts and serves the FullMAC MLME on a separate thread.
148///
149/// This will block until the FullMAC MLME has been initialized. MLME is considered "initialized"
150/// after it bootstraps USME, queries the vendor driver for supported hardware features, and
151/// creates the SME and MLME main loop futures. See the `start` function in this file for details.
152///
153/// Returns a handle to MLME on success, and an error if MLME failed to initialize.
154pub fn start_and_serve_on_separate_thread<F, D: DeviceOps + Send + 'static>(
155    device: D,
156    shutdown_completer: Completer<F>,
157) -> anyhow::Result<FullmacMlmeHandle>
158where
159    F: FnOnce(zx::sys::zx_status_t) + 'static,
160{
161    // Logger requires the executor to be initialized first.
162    let mut executor = fasync::LocalExecutorBuilder::new().build();
163    logger::init();
164
165    let (driver_event_sender, driver_event_stream) = mpsc::unbounded();
166    let driver_event_sender_clone = driver_event_sender.clone();
167    let inspector =
168        Inspector::new(fuchsia_inspect::InspectorConfig::default().size(INSPECT_VMO_SIZE_BYTES));
169
170    let (startup_sender, startup_receiver) = oneshot::channel();
171    let mlme_loop_join_handle = std::thread::spawn(move || {
172        // NOTE: Until MLME can be made async, MLME needs two threads to be able to
173        // send requests to the vendor driver and receive requests from the vendor driver
174        // simultaneously.
175        let mut executor = fasync::SendExecutorBuilder::new().num_threads(2).build();
176
177        info!("Starting WLAN MLME main loop");
178        let future = start_and_serve(
179            device,
180            driver_event_sender_clone,
181            driver_event_stream,
182            inspector,
183            startup_sender,
184        );
185        let result = executor.run(future);
186        shutdown_completer.reply(result);
187    });
188
189    match executor.run_singlethreaded(startup_receiver) {
190        Ok(Ok(())) => (),
191        Ok(Err(err)) => bail!(
192            "MLME failed to start with error {}. MLME main loop returned {:?}.",
193            err,
194            mlme_loop_join_handle.join()
195        ),
196        Err(oneshot::Canceled) => bail!(
197            "MLME thread dropped startup_sender. MLME main loop returned {:?}",
198            mlme_loop_join_handle.join()
199        ),
200    };
201
202    Ok(FullmacMlmeHandle {
203        driver_event_sender,
204        mlme_loop_join_handle: Some(mlme_loop_join_handle),
205        stop_requested: false,
206    })
207}
208
209/// Contains the initialized MLME main loop and SME futures.
210///
211/// Both futures do not hold references, so they should satisfy the 'static lifetime.
212struct StartedDriver {
213    mlme_main_loop_fut: BoxFuture<'static, anyhow::Result<()>>,
214    sme_fut: BoxFuture<'static, anyhow::Result<()>>,
215}
216
217/// This initializes the MLME and SME, then on successful initialization runs the MLME main loop
218/// future and SME futures concurrently until completion.
219///
220/// Notifies when startup is complete through |startup_sender|.
221///
222/// If initialization fails, then this exits immediately.
223///
224/// # Panics
225///
226/// This panics if sending over |startup_sender| returns an error. This probably means the
227/// thread that owns |startup_sender| already exited to an error/panic.
228async fn start_and_serve<D: DeviceOps + Send + 'static>(
229    device: D,
230    driver_event_sender: mpsc::UnboundedSender<FullmacDriverEvent>,
231    driver_event_stream: mpsc::UnboundedReceiver<FullmacDriverEvent>,
232    inspector: Inspector,
233    startup_sender: oneshot::Sender<Result<(), FullmacMlmeError>>,
234) -> Result<(), zx::Status> {
235    let StartedDriver { mlme_main_loop_fut, sme_fut } =
236        match start(device, driver_event_stream, driver_event_sender, inspector).await {
237            Ok(initialized_mlme) => {
238                if let Err(e) = startup_sender.send(Ok(())) {
239                    error!("Failed to send startup response: {:?}", e);
240                    return Err(zx::Status::INTERNAL);
241                }
242                initialized_mlme
243            }
244            Err(e) => {
245                if let Err(e) = startup_sender.send(Err(e)) {
246                    error!("Failed to send startup response: {:?}", e);
247                }
248                return Err(zx::Status::INTERNAL);
249            }
250        };
251
252    match futures::try_join!(mlme_main_loop_fut, sme_fut) {
253        Ok(_) => {
254            info!("MLME and/or SME event loop exited gracefully");
255            Ok(())
256        }
257        Err(e) => {
258            error!("MLME and/or SME event loop exited with error: {:?}", e);
259            Err(zx::Status::INTERNAL)
260        }
261    }
262}
263
264/// Starts the MLME and SME.
265///
266/// This:
267/// - Handles the channel exchange over WlanFullmacImpl::Start().
268/// - Retrieves the generic SME channel over the USME bootstrap channel.
269/// - Creates the SME future.
270/// - Creates the MLME main loop future.
271///
272/// On success, returns a `StartedDriver` that contains the MLME main loop and SME futures.
273async fn start<D: DeviceOps + Send + 'static>(
274    mut device: D,
275    driver_event_stream: mpsc::UnboundedReceiver<FullmacDriverEvent>,
276    driver_event_sender: mpsc::UnboundedSender<FullmacDriverEvent>,
277    inspector: Inspector,
278) -> Result<StartedDriver, FullmacMlmeError> {
279    let (fullmac_ifc_client_end, fullmac_ifc_request_stream) =
280        fidl::endpoints::create_request_stream();
281
282    let usme_bootstrap_protocol_channel =
283        device.init(fullmac_ifc_client_end).map_err(FullmacMlmeError::DeviceStartFailed)?;
284
285    let server = fidl::endpoints::ServerEnd::<fidl_sme::UsmeBootstrapMarker>::new(
286        usme_bootstrap_protocol_channel,
287    );
288
289    let mut usme_bootstrap_stream = server.into_stream();
290
291    let fidl_sme::UsmeBootstrapRequest::Start {
292        generic_sme_server,
293        legacy_privacy_support,
294        responder,
295        ..
296    } = usme_bootstrap_stream
297        .next()
298        .await
299        .ok_or(FullmacMlmeError::UsmeBootstrapStreamTerminated)?
300        .map_err(FullmacMlmeError::UsmeBootstrapStreamFailed)?;
301
302    let inspect_vmo =
303        inspector.duplicate_vmo().ok_or(FullmacMlmeError::FailedToDuplicateInspectVmo)?;
304
305    responder.send(inspect_vmo).map_err(FullmacMlmeError::FailedToRespondToUsmeBootstrapRequest)?;
306
307    let generic_sme_stream = generic_sme_server.into_stream();
308
309    // Create SME
310    let cfg = wlan_sme::Config {
311        wep_supported: legacy_privacy_support.wep_supported,
312        wpa1_supported: legacy_privacy_support.wpa1_supported,
313    };
314
315    let (mlme_event_sender, mlme_event_receiver) = mpsc::unbounded();
316    let mlme_event_sink = UnboundedSink::new(mlme_event_sender);
317
318    let device_info =
319        device.query_device_info().map_err(FullmacMlmeError::FailedToQueryVendorDriver)?;
320    let device_info = fullmac_to_mlme::convert_device_info(device_info)
321        .map_err(FullmacMlmeError::FailedToConvertVendorDriverQuery)?;
322
323    let security_support =
324        device.query_security_support().map_err(FullmacMlmeError::FailedToQueryVendorDriver)?;
325
326    let spectrum_management_support = device
327        .query_spectrum_management_support()
328        .map_err(FullmacMlmeError::FailedToQueryVendorDriver)?;
329
330    let (mlme_request_stream, sme_fut) = create_sme(
331        cfg.into(),
332        mlme_event_receiver,
333        &device_info,
334        security_support,
335        spectrum_management_support,
336        inspector,
337        generic_sme_stream,
338    )
339    .map_err(FullmacMlmeError::FailedToCreateSme)?;
340
341    let driver_event_sink = FullmacDriverEventSink(UnboundedSink::new(driver_event_sender));
342    let mlme_main_loop_fut = create_mlme_main_loop(
343        device,
344        mlme_request_stream,
345        mlme_event_sink,
346        driver_event_stream,
347        driver_event_sink,
348        fullmac_ifc_request_stream,
349    );
350
351    Ok(StartedDriver { mlme_main_loop_fut, sme_fut })
352}
353
354#[cfg(test)]
355mod tests {
356    use super::*;
357    use crate::device::test_utils::{DriverCall, FakeFullmacDevice, FakeFullmacDeviceMocks};
358    use assert_matches::assert_matches;
359    use fuchsia_async as fasync;
360    use fuchsia_sync::Mutex;
361    use futures::Future;
362    use futures::task::Poll;
363    use std::pin::Pin;
364    use std::sync::Arc;
365
366    #[test]
367    fn test_happy_path() {
368        let (mut h, mut test_fut) = TestHelper::set_up();
369        assert_matches!(h.exec.run_until_stalled(&mut test_fut), Poll::Pending);
370
371        let startup_result =
372            assert_matches!(h.startup_receiver.try_recv(), Ok(Some(result)) => result);
373        assert_matches!(startup_result, Ok(()));
374
375        let (client_sme_proxy, client_sme_server) =
376            fidl::endpoints::create_proxy::<fidl_sme::ClientSmeMarker>();
377
378        let mut client_sme_response_fut =
379            h.generic_sme_proxy.as_ref().unwrap().get_client_sme(client_sme_server);
380        assert_matches!(h.exec.run_until_stalled(&mut client_sme_response_fut), Poll::Pending);
381        assert_matches!(h.exec.run_until_stalled(&mut test_fut), Poll::Pending);
382        assert_matches!(
383            h.exec.run_until_stalled(&mut client_sme_response_fut),
384            Poll::Ready(Ok(Ok(())))
385        );
386
387        let mut status_fut = client_sme_proxy.status();
388        assert_matches!(h.exec.run_until_stalled(&mut status_fut), Poll::Pending);
389        assert_matches!(h.exec.run_until_stalled(&mut test_fut), Poll::Pending);
390        let status_result = assert_matches!(h.exec.run_until_stalled(&mut status_fut), Poll::Ready(result) => result);
391        assert_matches!(status_result, Ok(fidl_sme::ClientStatusResponse::Idle(_)));
392    }
393
394    #[test]
395    fn test_mlme_exits_due_to_driver_event() {
396        let (mut h, mut test_fut) = TestHelper::set_up();
397        assert_matches!(h.exec.run_until_stalled(&mut test_fut), Poll::Pending);
398
399        let startup_result =
400            assert_matches!(h.startup_receiver.try_recv(), Ok(Some(result)) => result);
401        assert_matches!(startup_result, Ok(()));
402
403        h.driver_event_sender
404            .unbounded_send(FullmacDriverEvent::Stop)
405            .expect("expect sending driver Stop event to succeed");
406        assert_matches!(h.exec.run_until_stalled(&mut test_fut), Poll::Ready(Ok(())));
407    }
408
409    #[test]
410    fn test_mlme_startup_fails_due_to_device_start() {
411        let (mut h, mut test_fut) = TestHelper::set_up();
412        h.fake_device.lock().start_fn_status_mock = Some(zx::sys::ZX_ERR_BAD_STATE);
413        assert_matches!(
414            h.exec.run_until_stalled(&mut test_fut),
415            Poll::Ready(Err(zx::Status::INTERNAL))
416        );
417
418        let startup_result =
419            assert_matches!(h.startup_receiver.try_recv(), Ok(Some(result)) => result);
420        assert_matches!(startup_result, Err(FullmacMlmeError::DeviceStartFailed(_)))
421    }
422
423    #[test]
424    fn test_mlme_startup_fails_due_to_usme_bootstrap_terminated() {
425        let bootstrap = false;
426        let (mut h, mut test_fut) = TestHelper::set_up_with_usme_bootstrap(bootstrap);
427        h.usme_bootstrap_proxy.take();
428        assert_matches!(
429            h.exec.run_until_stalled(&mut test_fut),
430            Poll::Ready(Err(zx::Status::INTERNAL))
431        );
432
433        let startup_result =
434            assert_matches!(h.startup_receiver.try_recv(), Ok(Some(result)) => result);
435        assert_matches!(startup_result, Err(FullmacMlmeError::UsmeBootstrapStreamTerminated));
436    }
437
438    #[test]
439    fn test_mlme_startup_fails_due_to_query_device_info_error() {
440        let (mut h, mut test_fut) = TestHelper::set_up();
441        h.fake_device.lock().query_device_info_mock = None;
442        assert_matches!(
443            h.exec.run_until_stalled(&mut test_fut),
444            Poll::Ready(Err(zx::Status::INTERNAL))
445        );
446
447        let startup_result =
448            assert_matches!(h.startup_receiver.try_recv(), Ok(Some(result)) => result);
449        assert_matches!(startup_result, Err(FullmacMlmeError::FailedToQueryVendorDriver(_)));
450    }
451
452    #[test]
453    fn test_mlme_startup_fails_due_to_query_security_support_error() {
454        let (mut h, mut test_fut) = TestHelper::set_up();
455        h.fake_device.lock().query_security_support_mock = None;
456        assert_matches!(
457            h.exec.run_until_stalled(&mut test_fut),
458            Poll::Ready(Err(zx::Status::INTERNAL))
459        );
460
461        let startup_result =
462            assert_matches!(h.startup_receiver.try_recv(), Ok(Some(result)) => result);
463        assert_matches!(startup_result, Err(FullmacMlmeError::FailedToQueryVendorDriver(_)));
464    }
465
466    #[test]
467    fn test_mlme_startup_fails_due_to_query_spectrum_management_support_error() {
468        let (mut h, mut test_fut) = TestHelper::set_up();
469        h.fake_device.lock().query_spectrum_management_support_mock = None;
470        assert_matches!(
471            h.exec.run_until_stalled(&mut test_fut),
472            Poll::Ready(Err(zx::Status::INTERNAL))
473        );
474
475        let startup_result =
476            assert_matches!(h.startup_receiver.try_recv(), Ok(Some(result)) => result);
477        assert_matches!(startup_result, Err(FullmacMlmeError::FailedToQueryVendorDriver(_)));
478    }
479
480    #[test]
481    fn test_mlme_startup_fails_due_to_failure_to_convert_query_device_info() {
482        let (mut h, mut test_fut) = TestHelper::set_up();
483        h.fake_device.lock().query_device_info_mock.as_mut().unwrap().role = None;
484        assert_matches!(
485            h.exec.run_until_stalled(&mut test_fut),
486            Poll::Ready(Err(zx::Status::INTERNAL))
487        );
488
489        let startup_result =
490            assert_matches!(h.startup_receiver.try_recv(), Ok(Some(result)) => result);
491        assert_matches!(startup_result, Err(FullmacMlmeError::FailedToConvertVendorDriverQuery(_)));
492    }
493
494    #[test]
495    fn test_mlme_startup_exits_due_to_sme_channel_closure() {
496        let (mut h, mut test_fut) = TestHelper::set_up();
497        assert_matches!(h.exec.run_until_stalled(&mut test_fut), Poll::Pending);
498        assert_matches!(h.startup_receiver.try_recv(), Ok(Some(Ok(()))));
499
500        std::mem::drop(h.generic_sme_proxy.take());
501        assert_matches!(
502            h.exec.run_until_stalled(&mut test_fut),
503            Poll::Ready(Err(zx::Status::INTERNAL))
504        );
505    }
506
507    #[test]
508    fn test_mlme_startup_exits_due_to_wlan_fullmac_impl_ifc_channel_closure() {
509        let (mut h, mut test_fut) = TestHelper::set_up();
510        assert_matches!(h.exec.run_until_stalled(&mut test_fut), Poll::Pending);
511        assert_matches!(h.startup_receiver.try_recv(), Ok(Some(Ok(()))));
512
513        std::mem::drop(h.fake_device.lock().fullmac_ifc_client_end.take());
514        assert_matches!(
515            h.exec.run_until_stalled(&mut test_fut),
516            Poll::Ready(Err(zx::Status::INTERNAL))
517        );
518    }
519
520    struct TestHelper {
521        fake_device: Arc<Mutex<FakeFullmacDeviceMocks>>,
522        driver_event_sender: mpsc::UnboundedSender<FullmacDriverEvent>,
523        usme_bootstrap_proxy: Option<fidl_sme::UsmeBootstrapProxy>,
524        _usme_bootstrap_result: Option<fidl::client::QueryResponseFut<zx::Vmo>>,
525        generic_sme_proxy: Option<fidl_sme::GenericSmeProxy>,
526        startup_receiver: oneshot::Receiver<Result<(), FullmacMlmeError>>,
527        _driver_calls: mpsc::UnboundedReceiver<DriverCall>,
528        exec: fasync::TestExecutor,
529    }
530
531    impl TestHelper {
532        pub fn set_up() -> (Self, Pin<Box<impl Future<Output = Result<(), zx::Status>>>>) {
533            let bootstrap = true;
534            Self::set_up_with_usme_bootstrap(bootstrap)
535        }
536
537        pub fn set_up_with_usme_bootstrap(
538            bootstrap: bool,
539        ) -> (Self, Pin<Box<impl Future<Output = Result<(), zx::Status>>>>) {
540            let exec = fasync::TestExecutor::new();
541
542            let (mut fake_device, _driver_calls) = FakeFullmacDevice::new();
543            let usme_bootstrap_proxy =
544                fake_device.usme_bootstrap_client_end.take().unwrap().into_proxy();
545
546            let (generic_sme_proxy, generic_sme_server_end) =
547                fidl::endpoints::create_proxy::<fidl_sme::GenericSmeMarker>();
548            let usme_bootstrap_result = if bootstrap {
549                Some(usme_bootstrap_proxy.start(
550                    generic_sme_server_end,
551                    &fidl_sme::LegacyPrivacySupport { wep_supported: false, wpa1_supported: false },
552                ))
553            } else {
554                None
555            };
556
557            let (driver_event_sender, driver_event_stream) = mpsc::unbounded();
558            let inspector = Inspector::default();
559            let (startup_sender, startup_receiver) = oneshot::channel();
560
561            let mocks = fake_device.mocks.clone();
562
563            let test_fut = Box::pin(start_and_serve(
564                fake_device,
565                driver_event_sender.clone(),
566                driver_event_stream,
567                inspector,
568                startup_sender,
569            ));
570
571            let test_helper = TestHelper {
572                fake_device: mocks,
573                driver_event_sender,
574                usme_bootstrap_proxy: Some(usme_bootstrap_proxy),
575                _usme_bootstrap_result: usme_bootstrap_result,
576                generic_sme_proxy: Some(generic_sme_proxy),
577                startup_receiver,
578                _driver_calls,
579                exec,
580            };
581            (test_helper, test_fut)
582        }
583    }
584}