pub fn on_sme_scan<F, CL>(
        &'a mut self,
        req: fidl_mlme::ScanRequest,
        build_channel_listener: F,
        chan_sched: &mut ChannelScheduler,
    ) -> Result<(), ScanError>
    where
        F: FnOnce(&'a mut Context, &'a mut Scanner) -> CL,
        CL: ChannelListener,
    {
        macro_rules! send_scan_end_and_return {
            ($txn_id:expr, $scan_error:expr, $self:expr) => {{
                let error = $scan_error;
                send_scan_end($txn_id, error.into(), &mut $self.ctx.device);
                return Err($scan_error);
            }};
        }

        if self.scanner.ongoing_scan.is_some() {
            send_scan_end_and_return!(req.txn_id, ScanError::Busy, self);
        }

        let channel_list = req.channel_list.as_ref().map(|list| list.as_slice()).unwrap_or(&[][..]);
        if channel_list.is_empty() {
            send_scan_end_and_return!(req.txn_id, ScanError::EmptyChannelList, self);
        }
        if channel_list.len() > banjo_hw_wlaninfo::WLAN_INFO_CHANNEL_LIST_MAX_CHANNELS {
            send_scan_end_and_return!(req.txn_id, ScanError::ChannelListTooLarge, self);
        }
        if req.max_channel_time < req.min_channel_time {
            send_scan_end_and_return!(req.txn_id, ScanError::MaxChannelTimeLtMin, self);
        }
        if req.ssid.len() > banjo_wlan_info::WLAN_MAX_SSID_LEN as usize {
            send_scan_end_and_return!(req.txn_id, ScanError::SsidTooLong, self);
        }

        let wlan_info = self.ctx.device.wlan_info().ifc_info;
        let hw_scan =
            (wlan_info.driver_features & banjo_hw_wlaninfo::WlanInfoDriverFeature::SCAN_OFFLOAD).0
                > 0;
        if hw_scan {
            let scan_type = if req.scan_type == fidl_mlme::ScanTypes::Active {
                banjo_wlan_mac::WlanHwScanType::ACTIVE
            } else {
                banjo_wlan_mac::WlanHwScanType::PASSIVE
            };
            let mut channels = [0; banjo_hw_wlaninfo::WLAN_INFO_CHANNEL_LIST_MAX_CHANNELS];
            channels[..channel_list.len()].copy_from_slice(channel_list);
            let mut ssid = [0; banjo_wlan_info::WLAN_MAX_SSID_LEN as usize];
            ssid[..req.ssid.len()].copy_from_slice(&req.ssid[..]);

            let config = banjo_wlan_mac::WlanHwScanConfig {
                scan_type,
                num_channels: channel_list.len() as u8,
                channels,
                ssid: banjo_wlan_info::WlanSsid { len: req.ssid.len() as u8, ssid },
            };
            if let Err(status) = self.ctx.device.start_hw_scan(&config) {
                self.scanner.ongoing_scan.take();
                send_scan_end_and_return!(req.txn_id, ScanError::StartHwScanFails(status), self);
            }
            self.scanner.ongoing_scan =
                Some(OngoingScan { req, seen_bss: HashMap::new(), probe_delay_timeout_id: None });
        } else {
            let channels = channel_list
                .iter()
                .map(|c| banjo_wlan_info::WlanChannel {
                    primary: *c,
                    cbw: banjo_wlan_info::WlanChannelBandwidth::_20,
                    secondary80: 0,
                })
                .collect();
            let max_channel_time = req.max_channel_time;
            // Note: for software scanning case, it's important to populate this beforehand because
            //       channel scheduler may `begin_requested_channel_time` immediately, and scanner
            //       needs these information to determine whether to send probe request.
            self.scanner.ongoing_scan =
                Some(OngoingScan { req, seen_bss: HashMap::new(), probe_delay_timeout_id: None });
            let mut listener = build_channel_listener(self.ctx, self.scanner);
            let dwell_time = TimeUnit(max_channel_time as u16).into();
            chan_sched
                .bind(&mut listener, ChannelListenerSource::Scanner)
                .queue_channels(channels, dwell_time);
        }
        Ok(())
    }
/// Handle scan request. Queue requested scan channels in channel scheduler.
///
/// If a scan request is in progress, or the new request has invalid argument (empty channel
/// list or larger min channel time than max), then the request is rejected.
Handle scan request. Queue requested scan channels in channel scheduler.
If a scan request is in progress, or the new request has invalid argument (empty channel
list or larger min channel time than max), then the request is rejected.
Handle scan request . Queue requested scan channels in channel scheduler . If a scan request is in progress or the new request has invalid argument ( empty channel list or larger min channel time than max ) then the request is rejected .
pub fn on_sme_scan<F, CL>(
        &'a mut self,
        req: fidl_mlme::ScanRequest,
        build_channel_listener: F,
        chan_sched: &mut ChannelScheduler,
    ) -> Result<(), ScanError>
    where
        F: FnOnce(&'a mut Context, &'a mut Scanner) -> CL,
        CL: ChannelListener,
    {
        macro_rules! send_scan_end_and_return {
            ($txn_id:expr, $scan_error:expr, $self:expr) => {{
                let error = $scan_error;
                send_scan_end($txn_id, error.into(), &mut $self.ctx.device);
                return Err($scan_error);
            }};
        }
        if self.scanner.ongoing_scan.is_some() {
            send_scan_end_and_return!(req.txn_id, ScanError::Busy, self);
        }
        let channel_list = req.channel_list.as_ref().map(|list| list.as_slice()).unwrap_or(&[][..]);
        if channel_list.is_empty() {
            send_scan_end_and_return!(req.txn_id, ScanError::EmptyChannelList, self);
        }
        if channel_list.len() > banjo_hw_wlaninfo::WLAN_INFO_CHANNEL_LIST_MAX_CHANNELS {
            send_scan_end_and_return!(req.txn_id, ScanError::ChannelListTooLarge, self);
        }
        if req.max_channel_time < req.min_channel_time {
            send_scan_end_and_return!(req.txn_id, ScanError::MaxChannelTimeLtMin, self);
        }
        if req.ssid.len() > banjo_wlan_info::WLAN_MAX_SSID_LEN as usize {
            send_scan_end_and_return!(req.txn_id, ScanError::SsidTooLong, self);
        }
        let wlan_info = self.ctx.device.wlan_info().ifc_info;
        let hw_scan =
            (wlan_info.driver_features & banjo_hw_wlaninfo::WlanInfoDriverFeature::SCAN_OFFLOAD).0
                > 0;
        if hw_scan {
            let scan_type = if req.scan_type == fidl_mlme::ScanTypes::Active {
                banjo_wlan_mac::WlanHwScanType::ACTIVE
            } else {
                banjo_wlan_mac::WlanHwScanType::PASSIVE
            };
            let mut channels = [0; banjo_hw_wlaninfo::WLAN_INFO_CHANNEL_LIST_MAX_CHANNELS];
            channels[..channel_list.len()].copy_from_slice(channel_list);
            let mut ssid = [0; banjo_wlan_info::WLAN_MAX_SSID_LEN as usize];
            ssid[..req.ssid.len()].copy_from_slice(&req.ssid[..]);
            let config = banjo_wlan_mac::WlanHwScanConfig {
                scan_type,
                num_channels: channel_list.len() as u8,
                channels,
                ssid: banjo_wlan_info::WlanSsid { len: req.ssid.len() as u8, ssid },
            };
            if let Err(status) = self.ctx.device.start_hw_scan(&config) {
                self.scanner.ongoing_scan.take();
                send_scan_end_and_return!(req.txn_id, ScanError::StartHwScanFails(status), self);
            }
            self.scanner.ongoing_scan =
                Some(OngoingScan { req, seen_bss: HashMap::new(), probe_delay_timeout_id: None });
        } else {
            let channels = channel_list
                .iter()
                .map(|c| banjo_wlan_info::WlanChannel {
                    primary: *c,
                    cbw: banjo_wlan_info::WlanChannelBandwidth::_20,
                    secondary80: 0,
                })
                .collect();
            let max_channel_time = req.max_channel_time;
            // Note: for software scanning case, it's important to populate this beforehand because
            //       channel scheduler may `begin_requested_channel_time` immediately, and scanner
            //       needs these information to determine whether to send probe request.
            self.scanner.ongoing_scan =
                Some(OngoingScan { req, seen_bss: HashMap::new(), probe_delay_timeout_id: None });
            let mut listener = build_channel_listener(self.ctx, self.scanner);
            let dwell_time = TimeUnit(max_channel_time as u16).into();
            chan_sched
                .bind(&mut listener, ChannelListenerSource::Scanner)
                .queue_channels(channels, dwell_time);
        }
        Ok(())
    }
pub fn on_sme_scan < F , CL > ( & ' a mut self , req : fidl_mlme :: ScanRequest , build_channel_listener : F , chan_sched : & mut ChannelScheduler , ) -> Result < ( ) , ScanError > where F : FnOnce ( & ' a mut Context , & ' a mut Scanner ) -> CL , CL : ChannelListener , { macro_rules! send_scan_end_and_return { ( $txn_id : expr $scan_error : expr $self : expr ) => { { let error $scan_error send_scan_end ( $txn_id error into ( ) mut $self ctx device ) return Err ( $scan_error ) } } ; } if self . scanner . ongoing_scan . is_some ( ) { send_scan_end_and_return ! ( req txn_id ScanError Busy self ) ; } let channel_list = req . channel_list . as_ref ( ) . map ( | list | list . as_slice ( ) ) . unwrap_or ( & [ ] [ .. ] ) ; if channel_list . is_empty ( ) { send_scan_end_and_return ! ( req txn_id ScanError EmptyChannelList self ) ; } if channel_list . len ( ) > banjo_hw_wlaninfo :: WLAN_INFO_CHANNEL_LIST_MAX_CHANNELS { send_scan_end_and_return ! ( req txn_id ScanError ChannelListTooLarge self ) ; } if req . max_channel_time < req . min_channel_time { send_scan_end_and_return ! ( req txn_id ScanError MaxChannelTimeLtMin self ) ; } if req . ssid . len ( ) > banjo_wlan_info :: WLAN_MAX_SSID_LEN as usize { send_scan_end_and_return ! ( req txn_id ScanError SsidTooLong self ) ; } let wlan_info = self . ctx . device . wlan_info ( ) . ifc_info ; let hw_scan = ( wlan_info . driver_features & banjo_hw_wlaninfo :: WlanInfoDriverFeature :: SCAN_OFFLOAD ) . 0 > 0 ; if hw_scan { let scan_type = if req . scan_type == fidl_mlme :: ScanTypes :: Active { banjo_wlan_mac :: WlanHwScanType :: ACTIVE } else { banjo_wlan_mac :: WlanHwScanType :: PASSIVE } ; let mut channels = [ 0 ; banjo_hw_wlaninfo :: WLAN_INFO_CHANNEL_LIST_MAX_CHANNELS ] ; channels [ .. channel_list . len ( ) ] . copy_from_slice ( channel_list ) ; let mut ssid = [ 0 ; banjo_wlan_info :: WLAN_MAX_SSID_LEN as usize ] ; ssid [ .. req . ssid . len ( ) ] . copy_from_slice ( & req . ssid [ .. ] ) ; let config = banjo_wlan_mac :: WlanHwScanConfig { scan_type , num_channels : channel_list . len ( ) as u8 , channels , ssid : banjo_wlan_info :: WlanSsid { len : req . ssid . len ( ) as u8 , ssid } , } ; if let Err ( status ) = self . ctx . device . start_hw_scan ( & config ) { self . scanner . ongoing_scan . take ( ) ; send_scan_end_and_return ! ( req txn_id ScanError StartHwScanFails ( status ) self ) ; } self . scanner . ongoing_scan = Some ( OngoingScan { req , seen_bss : HashMap :: new ( ) , probe_delay_timeout_id : None } ) ; } else { let channels = channel_list . iter ( ) . map ( | c | banjo_wlan_info :: WlanChannel { primary : * c , cbw : banjo_wlan_info :: WlanChannelBandwidth :: _20 , secondary80 : 0 , } ) . collect ( ) ; let max_channel_time = req . max_channel_time ; // Note: for software scanning case, it's important to populate this beforehand because //       channel scheduler may `begin_requested_channel_time` immediately, and scanner //       needs these information to determine whether to send probe request. self . scanner . ongoing_scan = Some ( OngoingScan { req , seen_bss : HashMap :: new ( ) , probe_delay_timeout_id : None } ) ; let mut listener = build_channel_listener ( self . ctx , self . scanner ) ; let dwell_time = TimeUnit ( max_channel_time as u16 ) . into ( ) ; chan_sched . bind ( & mut listener , ChannelListenerSource :: Scanner ) . queue_channels ( channels , dwell_time ) ; } Ok ( ( ) ) }
Handle scan request.
Handle scan request .
&'a mut self
req
fidl_mlme::ScanRequest
build_channel_listener
F
chan_sched
&mut ChannelScheduler
&'a mut self
req
fidl_mlme::ScanRequest
build_channel_listener
F
chan_sched
&mut ChannelScheduler