xref: /aosp_15_r20/tools/netsim/rust/daemon/src/wireless/wifi.rs (revision cf78ab8cffb8fc9207af348f23af247fb04370a6)
1*cf78ab8cSAndroid Build Coastguard Worker // Copyright 2023 Google LLC
2*cf78ab8cSAndroid Build Coastguard Worker //
3*cf78ab8cSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*cf78ab8cSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*cf78ab8cSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*cf78ab8cSAndroid Build Coastguard Worker //
7*cf78ab8cSAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*cf78ab8cSAndroid Build Coastguard Worker //
9*cf78ab8cSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*cf78ab8cSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*cf78ab8cSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*cf78ab8cSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*cf78ab8cSAndroid Build Coastguard Worker // limitations under the License.
14*cf78ab8cSAndroid Build Coastguard Worker 
15*cf78ab8cSAndroid Build Coastguard Worker use crate::devices::chip::ChipIdentifier;
16*cf78ab8cSAndroid Build Coastguard Worker use crate::wifi::hostapd;
17*cf78ab8cSAndroid Build Coastguard Worker use crate::wifi::libslirp;
18*cf78ab8cSAndroid Build Coastguard Worker #[cfg(not(feature = "cuttlefish"))]
19*cf78ab8cSAndroid Build Coastguard Worker use crate::wifi::mdns_forwarder;
20*cf78ab8cSAndroid Build Coastguard Worker use crate::wifi::medium::Medium;
21*cf78ab8cSAndroid Build Coastguard Worker use crate::wireless::{packet::handle_response, WirelessAdaptor, WirelessAdaptorImpl};
22*cf78ab8cSAndroid Build Coastguard Worker use anyhow;
23*cf78ab8cSAndroid Build Coastguard Worker use bytes::Bytes;
24*cf78ab8cSAndroid Build Coastguard Worker use log::{info, warn};
25*cf78ab8cSAndroid Build Coastguard Worker use netsim_proto::config::WiFi as WiFiConfig;
26*cf78ab8cSAndroid Build Coastguard Worker use netsim_proto::model::Chip as ProtoChip;
27*cf78ab8cSAndroid Build Coastguard Worker use netsim_proto::stats::{netsim_radio_stats, NetsimRadioStats as ProtoRadioStats};
28*cf78ab8cSAndroid Build Coastguard Worker use protobuf::MessageField;
29*cf78ab8cSAndroid Build Coastguard Worker use std::sync::atomic::Ordering;
30*cf78ab8cSAndroid Build Coastguard Worker use std::sync::{mpsc, Arc, OnceLock};
31*cf78ab8cSAndroid Build Coastguard Worker use std::thread;
32*cf78ab8cSAndroid Build Coastguard Worker use std::time::{Duration, Instant};
33*cf78ab8cSAndroid Build Coastguard Worker 
34*cf78ab8cSAndroid Build Coastguard Worker /// Parameters for creating Wifi chips
35*cf78ab8cSAndroid Build Coastguard Worker /// allow(dead_code) due to not being used in unit tests
36*cf78ab8cSAndroid Build Coastguard Worker #[allow(dead_code)]
37*cf78ab8cSAndroid Build Coastguard Worker pub struct CreateParams {}
38*cf78ab8cSAndroid Build Coastguard Worker 
39*cf78ab8cSAndroid Build Coastguard Worker /// Wifi struct will keep track of chip_id
40*cf78ab8cSAndroid Build Coastguard Worker pub struct Wifi {
41*cf78ab8cSAndroid Build Coastguard Worker     chip_id: ChipIdentifier,
42*cf78ab8cSAndroid Build Coastguard Worker }
43*cf78ab8cSAndroid Build Coastguard Worker 
44*cf78ab8cSAndroid Build Coastguard Worker pub struct WifiManager {
45*cf78ab8cSAndroid Build Coastguard Worker     medium: Medium,
46*cf78ab8cSAndroid Build Coastguard Worker     tx_request: mpsc::Sender<(u32, Bytes)>,
47*cf78ab8cSAndroid Build Coastguard Worker     slirp: libslirp::LibSlirp,
48*cf78ab8cSAndroid Build Coastguard Worker     hostapd: Arc<hostapd::Hostapd>,
49*cf78ab8cSAndroid Build Coastguard Worker }
50*cf78ab8cSAndroid Build Coastguard Worker 
51*cf78ab8cSAndroid Build Coastguard Worker impl WifiManager {
new( tx_request: mpsc::Sender<(u32, Bytes)>, slirp: libslirp::LibSlirp, hostapd: hostapd::Hostapd, ) -> WifiManager52*cf78ab8cSAndroid Build Coastguard Worker     pub fn new(
53*cf78ab8cSAndroid Build Coastguard Worker         tx_request: mpsc::Sender<(u32, Bytes)>,
54*cf78ab8cSAndroid Build Coastguard Worker         slirp: libslirp::LibSlirp,
55*cf78ab8cSAndroid Build Coastguard Worker         hostapd: hostapd::Hostapd,
56*cf78ab8cSAndroid Build Coastguard Worker     ) -> WifiManager {
57*cf78ab8cSAndroid Build Coastguard Worker         let hostapd = Arc::new(hostapd);
58*cf78ab8cSAndroid Build Coastguard Worker         WifiManager {
59*cf78ab8cSAndroid Build Coastguard Worker             medium: Medium::new(medium_callback, hostapd.clone()),
60*cf78ab8cSAndroid Build Coastguard Worker             tx_request,
61*cf78ab8cSAndroid Build Coastguard Worker             slirp,
62*cf78ab8cSAndroid Build Coastguard Worker             hostapd,
63*cf78ab8cSAndroid Build Coastguard Worker         }
64*cf78ab8cSAndroid Build Coastguard Worker     }
65*cf78ab8cSAndroid Build Coastguard Worker 
66*cf78ab8cSAndroid Build Coastguard Worker     /// Starts background threads:
67*cf78ab8cSAndroid Build Coastguard Worker     /// * One to handle requests from medium.
68*cf78ab8cSAndroid Build Coastguard Worker     /// * One to handle IEEE802.3 responses from network.
69*cf78ab8cSAndroid Build Coastguard Worker     /// * One to handle IEEE802.11 responses from hostapd.
start( &self, rx_request: mpsc::Receiver<(u32, Bytes)>, rx_ieee8023_response: mpsc::Receiver<Bytes>, rx_ieee80211_response: mpsc::Receiver<Bytes>, tx_ieee8023_response: mpsc::Sender<Bytes>, forward_host_mdns: bool, ) -> anyhow::Result<()>70*cf78ab8cSAndroid Build Coastguard Worker     pub fn start(
71*cf78ab8cSAndroid Build Coastguard Worker         &self,
72*cf78ab8cSAndroid Build Coastguard Worker         rx_request: mpsc::Receiver<(u32, Bytes)>,
73*cf78ab8cSAndroid Build Coastguard Worker         rx_ieee8023_response: mpsc::Receiver<Bytes>,
74*cf78ab8cSAndroid Build Coastguard Worker         rx_ieee80211_response: mpsc::Receiver<Bytes>,
75*cf78ab8cSAndroid Build Coastguard Worker         tx_ieee8023_response: mpsc::Sender<Bytes>,
76*cf78ab8cSAndroid Build Coastguard Worker         forward_host_mdns: bool,
77*cf78ab8cSAndroid Build Coastguard Worker     ) -> anyhow::Result<()> {
78*cf78ab8cSAndroid Build Coastguard Worker         self.start_request_thread(rx_request)?;
79*cf78ab8cSAndroid Build Coastguard Worker         self.start_ieee8023_response_thread(rx_ieee8023_response)?;
80*cf78ab8cSAndroid Build Coastguard Worker         self.start_ieee80211_response_thread(rx_ieee80211_response)?;
81*cf78ab8cSAndroid Build Coastguard Worker         if forward_host_mdns {
82*cf78ab8cSAndroid Build Coastguard Worker             self.start_mdns_forwarder_thread(tx_ieee8023_response)?;
83*cf78ab8cSAndroid Build Coastguard Worker         }
84*cf78ab8cSAndroid Build Coastguard Worker         Ok(())
85*cf78ab8cSAndroid Build Coastguard Worker     }
86*cf78ab8cSAndroid Build Coastguard Worker 
start_request_thread(&self, rx_request: mpsc::Receiver<(u32, Bytes)>) -> anyhow::Result<()>87*cf78ab8cSAndroid Build Coastguard Worker     fn start_request_thread(&self, rx_request: mpsc::Receiver<(u32, Bytes)>) -> anyhow::Result<()> {
88*cf78ab8cSAndroid Build Coastguard Worker         thread::Builder::new().name("Wi-Fi HwsimMsg request".to_string()).spawn(move || {
89*cf78ab8cSAndroid Build Coastguard Worker             const POLL_INTERVAL: Duration = Duration::from_millis(1);
90*cf78ab8cSAndroid Build Coastguard Worker             let mut next_instant = Instant::now() + POLL_INTERVAL;
91*cf78ab8cSAndroid Build Coastguard Worker 
92*cf78ab8cSAndroid Build Coastguard Worker             loop {
93*cf78ab8cSAndroid Build Coastguard Worker                 let this_instant = Instant::now();
94*cf78ab8cSAndroid Build Coastguard Worker                 let timeout = if next_instant > this_instant {
95*cf78ab8cSAndroid Build Coastguard Worker                     next_instant - this_instant
96*cf78ab8cSAndroid Build Coastguard Worker                 } else {
97*cf78ab8cSAndroid Build Coastguard Worker                     Duration::ZERO
98*cf78ab8cSAndroid Build Coastguard Worker                 };
99*cf78ab8cSAndroid Build Coastguard Worker                 match rx_request.recv_timeout(timeout) {
100*cf78ab8cSAndroid Build Coastguard Worker                     Ok((chip_id, packet)) => {
101*cf78ab8cSAndroid Build Coastguard Worker                         if let Some(processor) =
102*cf78ab8cSAndroid Build Coastguard Worker                             get_wifi_manager().medium.get_processor(chip_id, &packet)
103*cf78ab8cSAndroid Build Coastguard Worker                         {
104*cf78ab8cSAndroid Build Coastguard Worker                             get_wifi_manager().medium.ack_frame(chip_id, &processor.frame);
105*cf78ab8cSAndroid Build Coastguard Worker                             if processor.hostapd {
106*cf78ab8cSAndroid Build Coastguard Worker                                 let ieee80211: Bytes = processor.get_ieee80211_bytes();
107*cf78ab8cSAndroid Build Coastguard Worker                                 if let Err(err) = get_wifi_manager().hostapd.input(ieee80211) {
108*cf78ab8cSAndroid Build Coastguard Worker                                     warn!("Failed to call hostapd input: {:?}", err);
109*cf78ab8cSAndroid Build Coastguard Worker                                 };
110*cf78ab8cSAndroid Build Coastguard Worker                             }
111*cf78ab8cSAndroid Build Coastguard Worker                             if processor.network {
112*cf78ab8cSAndroid Build Coastguard Worker                                 match processor.get_ieee80211().to_ieee8023() {
113*cf78ab8cSAndroid Build Coastguard Worker                                     Ok(ethernet_frame) => {
114*cf78ab8cSAndroid Build Coastguard Worker                                         get_wifi_manager().slirp.input(ethernet_frame.into())
115*cf78ab8cSAndroid Build Coastguard Worker                                     }
116*cf78ab8cSAndroid Build Coastguard Worker                                     Err(err) => {
117*cf78ab8cSAndroid Build Coastguard Worker                                         warn!("Failed to convert 802.11 to 802.3: {}", err)
118*cf78ab8cSAndroid Build Coastguard Worker                                     }
119*cf78ab8cSAndroid Build Coastguard Worker                                 }
120*cf78ab8cSAndroid Build Coastguard Worker                             }
121*cf78ab8cSAndroid Build Coastguard Worker                             if processor.wmedium {
122*cf78ab8cSAndroid Build Coastguard Worker                                 // Decrypt the frame using the sender's key and re-encrypt it using the receiver's key for peer-to-peer communication through hostapd (broadcast or unicast).
123*cf78ab8cSAndroid Build Coastguard Worker                                 let ieee80211 = processor.get_ieee80211().clone();
124*cf78ab8cSAndroid Build Coastguard Worker                                 get_wifi_manager().medium.queue_frame(processor.frame, ieee80211);
125*cf78ab8cSAndroid Build Coastguard Worker                             }
126*cf78ab8cSAndroid Build Coastguard Worker                         }
127*cf78ab8cSAndroid Build Coastguard Worker                     }
128*cf78ab8cSAndroid Build Coastguard Worker                     _ => {
129*cf78ab8cSAndroid Build Coastguard Worker                         next_instant = Instant::now() + POLL_INTERVAL;
130*cf78ab8cSAndroid Build Coastguard Worker                     }
131*cf78ab8cSAndroid Build Coastguard Worker                 };
132*cf78ab8cSAndroid Build Coastguard Worker             }
133*cf78ab8cSAndroid Build Coastguard Worker         })?;
134*cf78ab8cSAndroid Build Coastguard Worker         Ok(())
135*cf78ab8cSAndroid Build Coastguard Worker     }
136*cf78ab8cSAndroid Build Coastguard Worker 
137*cf78ab8cSAndroid Build Coastguard Worker     /// Starts a dedicated thread to process IEEE 802.3 (Ethernet) responses from the network.
138*cf78ab8cSAndroid Build Coastguard Worker     ///
139*cf78ab8cSAndroid Build Coastguard Worker     /// This thread continuously receives IEEE 802.3 response packets from the `rx_ieee8023_response` channel
140*cf78ab8cSAndroid Build Coastguard Worker     /// and forwards them to the Wi-Fi manager's medium.
start_ieee8023_response_thread( &self, rx_ieee8023_response: mpsc::Receiver<Bytes>, ) -> anyhow::Result<()>141*cf78ab8cSAndroid Build Coastguard Worker     fn start_ieee8023_response_thread(
142*cf78ab8cSAndroid Build Coastguard Worker         &self,
143*cf78ab8cSAndroid Build Coastguard Worker         rx_ieee8023_response: mpsc::Receiver<Bytes>,
144*cf78ab8cSAndroid Build Coastguard Worker     ) -> anyhow::Result<()> {
145*cf78ab8cSAndroid Build Coastguard Worker         thread::Builder::new().name("Wi-Fi IEEE802.3 response".to_string()).spawn(move || {
146*cf78ab8cSAndroid Build Coastguard Worker             for packet in rx_ieee8023_response {
147*cf78ab8cSAndroid Build Coastguard Worker                 get_wifi_manager().medium.process_ieee8023_response(&packet);
148*cf78ab8cSAndroid Build Coastguard Worker             }
149*cf78ab8cSAndroid Build Coastguard Worker         })?;
150*cf78ab8cSAndroid Build Coastguard Worker         Ok(())
151*cf78ab8cSAndroid Build Coastguard Worker     }
152*cf78ab8cSAndroid Build Coastguard Worker 
153*cf78ab8cSAndroid Build Coastguard Worker     /// Starts a dedicated thread to process IEEE 802.11 responses from hostapd.
154*cf78ab8cSAndroid Build Coastguard Worker     ///
155*cf78ab8cSAndroid Build Coastguard Worker     /// This thread continuously receives IEEE 802.11 response packets from the hostapd response channel
156*cf78ab8cSAndroid Build Coastguard Worker     /// and forwards them to the Wi-Fi manager's medium.
start_ieee80211_response_thread( &self, rx_ieee80211_response: mpsc::Receiver<Bytes>, ) -> anyhow::Result<()>157*cf78ab8cSAndroid Build Coastguard Worker     fn start_ieee80211_response_thread(
158*cf78ab8cSAndroid Build Coastguard Worker         &self,
159*cf78ab8cSAndroid Build Coastguard Worker         rx_ieee80211_response: mpsc::Receiver<Bytes>,
160*cf78ab8cSAndroid Build Coastguard Worker     ) -> anyhow::Result<()> {
161*cf78ab8cSAndroid Build Coastguard Worker         thread::Builder::new().name("Wi-Fi IEEE802.11 response".to_string()).spawn(move || {
162*cf78ab8cSAndroid Build Coastguard Worker             for packet in rx_ieee80211_response {
163*cf78ab8cSAndroid Build Coastguard Worker                 get_wifi_manager().medium.process_ieee80211_response(&packet);
164*cf78ab8cSAndroid Build Coastguard Worker             }
165*cf78ab8cSAndroid Build Coastguard Worker         })?;
166*cf78ab8cSAndroid Build Coastguard Worker         Ok(())
167*cf78ab8cSAndroid Build Coastguard Worker     }
168*cf78ab8cSAndroid Build Coastguard Worker 
169*cf78ab8cSAndroid Build Coastguard Worker     #[cfg(feature = "cuttlefish")]
start_mdns_forwarder_thread( &self, _tx_ieee8023_response: mpsc::Sender<Bytes>, ) -> anyhow::Result<()>170*cf78ab8cSAndroid Build Coastguard Worker     fn start_mdns_forwarder_thread(
171*cf78ab8cSAndroid Build Coastguard Worker         &self,
172*cf78ab8cSAndroid Build Coastguard Worker         _tx_ieee8023_response: mpsc::Sender<Bytes>,
173*cf78ab8cSAndroid Build Coastguard Worker     ) -> anyhow::Result<()> {
174*cf78ab8cSAndroid Build Coastguard Worker         Ok(())
175*cf78ab8cSAndroid Build Coastguard Worker     }
176*cf78ab8cSAndroid Build Coastguard Worker 
177*cf78ab8cSAndroid Build Coastguard Worker     #[cfg(not(feature = "cuttlefish"))]
start_mdns_forwarder_thread( &self, tx_ieee8023_response: mpsc::Sender<Bytes>, ) -> anyhow::Result<()>178*cf78ab8cSAndroid Build Coastguard Worker     fn start_mdns_forwarder_thread(
179*cf78ab8cSAndroid Build Coastguard Worker         &self,
180*cf78ab8cSAndroid Build Coastguard Worker         tx_ieee8023_response: mpsc::Sender<Bytes>,
181*cf78ab8cSAndroid Build Coastguard Worker     ) -> anyhow::Result<()> {
182*cf78ab8cSAndroid Build Coastguard Worker         info!("Start mDNS forwarder thread");
183*cf78ab8cSAndroid Build Coastguard Worker         thread::Builder::new().name("Wi-Fi mDNS forwarder".to_string()).spawn(move || {
184*cf78ab8cSAndroid Build Coastguard Worker             if let Err(e) = mdns_forwarder::run_mdns_forwarder(tx_ieee8023_response) {
185*cf78ab8cSAndroid Build Coastguard Worker                 warn!("Failed to start mDNS forwarder: {}", e);
186*cf78ab8cSAndroid Build Coastguard Worker             }
187*cf78ab8cSAndroid Build Coastguard Worker         })?;
188*cf78ab8cSAndroid Build Coastguard Worker         Ok(())
189*cf78ab8cSAndroid Build Coastguard Worker     }
190*cf78ab8cSAndroid Build Coastguard Worker }
191*cf78ab8cSAndroid Build Coastguard Worker 
192*cf78ab8cSAndroid Build Coastguard Worker // Allocator for chip identifiers.
193*cf78ab8cSAndroid Build Coastguard Worker static WIFI_MANAGER: OnceLock<WifiManager> = OnceLock::new();
194*cf78ab8cSAndroid Build Coastguard Worker 
get_wifi_manager() -> &'static WifiManager195*cf78ab8cSAndroid Build Coastguard Worker fn get_wifi_manager() -> &'static WifiManager {
196*cf78ab8cSAndroid Build Coastguard Worker     WIFI_MANAGER.get().expect("WifiManager not initialized")
197*cf78ab8cSAndroid Build Coastguard Worker }
198*cf78ab8cSAndroid Build Coastguard Worker 
199*cf78ab8cSAndroid Build Coastguard Worker impl Drop for Wifi {
drop(&mut self)200*cf78ab8cSAndroid Build Coastguard Worker     fn drop(&mut self) {
201*cf78ab8cSAndroid Build Coastguard Worker         get_wifi_manager().medium.remove(self.chip_id.0);
202*cf78ab8cSAndroid Build Coastguard Worker     }
203*cf78ab8cSAndroid Build Coastguard Worker }
204*cf78ab8cSAndroid Build Coastguard Worker 
205*cf78ab8cSAndroid Build Coastguard Worker impl WirelessAdaptor for Wifi {
handle_request(&self, packet: &Bytes)206*cf78ab8cSAndroid Build Coastguard Worker     fn handle_request(&self, packet: &Bytes) {
207*cf78ab8cSAndroid Build Coastguard Worker         if let Err(e) = get_wifi_manager().tx_request.send((self.chip_id.0, packet.clone())) {
208*cf78ab8cSAndroid Build Coastguard Worker             warn!("Failed wifi handle_request: {:?}", e);
209*cf78ab8cSAndroid Build Coastguard Worker         }
210*cf78ab8cSAndroid Build Coastguard Worker     }
211*cf78ab8cSAndroid Build Coastguard Worker 
reset(&self)212*cf78ab8cSAndroid Build Coastguard Worker     fn reset(&self) {
213*cf78ab8cSAndroid Build Coastguard Worker         get_wifi_manager().medium.reset(self.chip_id.0);
214*cf78ab8cSAndroid Build Coastguard Worker     }
215*cf78ab8cSAndroid Build Coastguard Worker 
get(&self) -> ProtoChip216*cf78ab8cSAndroid Build Coastguard Worker     fn get(&self) -> ProtoChip {
217*cf78ab8cSAndroid Build Coastguard Worker         let mut chip_proto = ProtoChip::new();
218*cf78ab8cSAndroid Build Coastguard Worker         if let Some(client) = get_wifi_manager().medium.get(self.chip_id.0) {
219*cf78ab8cSAndroid Build Coastguard Worker             chip_proto.mut_wifi().state = Some(client.enabled.load(Ordering::Relaxed));
220*cf78ab8cSAndroid Build Coastguard Worker             chip_proto.mut_wifi().tx_count = client.tx_count.load(Ordering::Relaxed) as i32;
221*cf78ab8cSAndroid Build Coastguard Worker             chip_proto.mut_wifi().rx_count = client.rx_count.load(Ordering::Relaxed) as i32;
222*cf78ab8cSAndroid Build Coastguard Worker         }
223*cf78ab8cSAndroid Build Coastguard Worker         chip_proto
224*cf78ab8cSAndroid Build Coastguard Worker     }
225*cf78ab8cSAndroid Build Coastguard Worker 
patch(&self, patch: &ProtoChip)226*cf78ab8cSAndroid Build Coastguard Worker     fn patch(&self, patch: &ProtoChip) {
227*cf78ab8cSAndroid Build Coastguard Worker         if patch.wifi().state.is_some() {
228*cf78ab8cSAndroid Build Coastguard Worker             get_wifi_manager().medium.set_enabled(self.chip_id.0, patch.wifi().state.unwrap());
229*cf78ab8cSAndroid Build Coastguard Worker         }
230*cf78ab8cSAndroid Build Coastguard Worker     }
231*cf78ab8cSAndroid Build Coastguard Worker 
get_stats(&self, duration_secs: u64) -> Vec<ProtoRadioStats>232*cf78ab8cSAndroid Build Coastguard Worker     fn get_stats(&self, duration_secs: u64) -> Vec<ProtoRadioStats> {
233*cf78ab8cSAndroid Build Coastguard Worker         let mut stats_proto = ProtoRadioStats::new();
234*cf78ab8cSAndroid Build Coastguard Worker         stats_proto.set_duration_secs(duration_secs);
235*cf78ab8cSAndroid Build Coastguard Worker         stats_proto.set_kind(netsim_radio_stats::Kind::WIFI);
236*cf78ab8cSAndroid Build Coastguard Worker         let chip_proto = self.get();
237*cf78ab8cSAndroid Build Coastguard Worker         if chip_proto.has_wifi() {
238*cf78ab8cSAndroid Build Coastguard Worker             stats_proto.set_tx_count(chip_proto.wifi().tx_count);
239*cf78ab8cSAndroid Build Coastguard Worker             stats_proto.set_rx_count(chip_proto.wifi().rx_count);
240*cf78ab8cSAndroid Build Coastguard Worker         }
241*cf78ab8cSAndroid Build Coastguard Worker         vec![stats_proto]
242*cf78ab8cSAndroid Build Coastguard Worker     }
243*cf78ab8cSAndroid Build Coastguard Worker }
244*cf78ab8cSAndroid Build Coastguard Worker 
medium_callback(id: u32, packet: &Bytes)245*cf78ab8cSAndroid Build Coastguard Worker fn medium_callback(id: u32, packet: &Bytes) {
246*cf78ab8cSAndroid Build Coastguard Worker     handle_response(ChipIdentifier(id), packet);
247*cf78ab8cSAndroid Build Coastguard Worker }
248*cf78ab8cSAndroid Build Coastguard Worker 
249*cf78ab8cSAndroid Build Coastguard Worker /// Create a new Emulated Wifi Chip
250*cf78ab8cSAndroid Build Coastguard Worker /// allow(dead_code) due to not being used in unit tests
251*cf78ab8cSAndroid Build Coastguard Worker #[allow(dead_code)]
new(_params: &CreateParams, chip_id: ChipIdentifier) -> WirelessAdaptorImpl252*cf78ab8cSAndroid Build Coastguard Worker pub fn new(_params: &CreateParams, chip_id: ChipIdentifier) -> WirelessAdaptorImpl {
253*cf78ab8cSAndroid Build Coastguard Worker     get_wifi_manager().medium.add(chip_id.0);
254*cf78ab8cSAndroid Build Coastguard Worker     info!("WiFi WirelessAdaptor created chip_id: {chip_id}");
255*cf78ab8cSAndroid Build Coastguard Worker     let wifi = Wifi { chip_id };
256*cf78ab8cSAndroid Build Coastguard Worker     Box::new(wifi)
257*cf78ab8cSAndroid Build Coastguard Worker }
258*cf78ab8cSAndroid Build Coastguard Worker 
259*cf78ab8cSAndroid Build Coastguard Worker /// Starts the WiFi service.
wifi_start(config: &MessageField<WiFiConfig>, forward_host_mdns: bool)260*cf78ab8cSAndroid Build Coastguard Worker pub fn wifi_start(config: &MessageField<WiFiConfig>, forward_host_mdns: bool) {
261*cf78ab8cSAndroid Build Coastguard Worker     let (tx_request, rx_request) = mpsc::channel::<(u32, Bytes)>();
262*cf78ab8cSAndroid Build Coastguard Worker     let (tx_ieee8023_response, rx_ieee8023_response) = mpsc::channel::<Bytes>();
263*cf78ab8cSAndroid Build Coastguard Worker     let (tx_ieee80211_response, rx_ieee80211_response) = mpsc::channel::<Bytes>();
264*cf78ab8cSAndroid Build Coastguard Worker     let tx_ieee8023_response_clone = tx_ieee8023_response.clone();
265*cf78ab8cSAndroid Build Coastguard Worker     let wifi_config = config.clone().unwrap_or_default();
266*cf78ab8cSAndroid Build Coastguard Worker     let slirp_opt = wifi_config.slirp_options.as_ref().unwrap_or_default().clone();
267*cf78ab8cSAndroid Build Coastguard Worker     let slirp = libslirp::slirp_run(slirp_opt, tx_ieee8023_response_clone)
268*cf78ab8cSAndroid Build Coastguard Worker         .map_err(|e| warn!("Failed to run libslirp. {e}"))
269*cf78ab8cSAndroid Build Coastguard Worker         .unwrap();
270*cf78ab8cSAndroid Build Coastguard Worker 
271*cf78ab8cSAndroid Build Coastguard Worker     let hostapd_opt = wifi_config.hostapd_options.as_ref().unwrap_or_default().clone();
272*cf78ab8cSAndroid Build Coastguard Worker     let hostapd = hostapd::hostapd_run(hostapd_opt, tx_ieee80211_response)
273*cf78ab8cSAndroid Build Coastguard Worker         .map_err(|e| warn!("Failed to run hostapd. {e}"))
274*cf78ab8cSAndroid Build Coastguard Worker         .unwrap();
275*cf78ab8cSAndroid Build Coastguard Worker 
276*cf78ab8cSAndroid Build Coastguard Worker     let _ = WIFI_MANAGER.set(WifiManager::new(tx_request, slirp, hostapd));
277*cf78ab8cSAndroid Build Coastguard Worker 
278*cf78ab8cSAndroid Build Coastguard Worker     if let Err(e) = get_wifi_manager().start(
279*cf78ab8cSAndroid Build Coastguard Worker         rx_request,
280*cf78ab8cSAndroid Build Coastguard Worker         rx_ieee8023_response,
281*cf78ab8cSAndroid Build Coastguard Worker         rx_ieee80211_response,
282*cf78ab8cSAndroid Build Coastguard Worker         tx_ieee8023_response,
283*cf78ab8cSAndroid Build Coastguard Worker         forward_host_mdns,
284*cf78ab8cSAndroid Build Coastguard Worker     ) {
285*cf78ab8cSAndroid Build Coastguard Worker         warn!("Failed to start Wi-Fi manager: {}", e);
286*cf78ab8cSAndroid Build Coastguard Worker     }
287*cf78ab8cSAndroid Build Coastguard Worker }
288*cf78ab8cSAndroid Build Coastguard Worker 
289*cf78ab8cSAndroid Build Coastguard Worker /// Stops the WiFi service.
wifi_stop()290*cf78ab8cSAndroid Build Coastguard Worker pub fn wifi_stop() {
291*cf78ab8cSAndroid Build Coastguard Worker     // TODO: stop hostapd
292*cf78ab8cSAndroid Build Coastguard Worker }
293