1#![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
17pub mod ap;
18pub mod client;
19pub mod serve;
20#[cfg(test)]
21pub mod test_utils;
22
23use fidl_fuchsia_wlan_common as fidl_common;
24use fidl_fuchsia_wlan_ieee80211 as fidl_ieee80211;
25use fidl_fuchsia_wlan_mlme::{self as fidl_mlme, MlmeEvent};
26use fidl_fuchsia_wlan_stats as fidl_stats;
27use futures::channel::mpsc;
28use thiserror::Error;
29use wlan_common::sink::UnboundedSink;
30use wlan_common::timer;
31
32#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd)]
33pub struct Config {
34 pub wep_supported: bool,
35 pub wpa1_supported: bool,
36}
37
38impl Config {
39 pub fn with_wep(mut self) -> Self {
40 self.wep_supported = true;
41 self
42 }
43
44 pub fn with_wpa1(mut self) -> Self {
45 self.wpa1_supported = true;
46 self
47 }
48}
49
50#[derive(Debug)]
51pub enum MlmeRequest {
52 Scan(fidl_mlme::ScanRequest),
53 AuthResponse(fidl_mlme::AuthenticateResponse),
54 AssocResponse(fidl_mlme::AssociateResponse),
55 Connect(fidl_mlme::ConnectRequest),
56 Reconnect(fidl_mlme::ReconnectRequest),
57 Roam(fidl_mlme::RoamRequest),
58 Deauthenticate(fidl_mlme::DeauthenticateRequest),
59 Disassociate(fidl_mlme::DisassociateRequest),
60 Eapol(fidl_mlme::EapolRequest),
61 SetKeys(fidl_mlme::SetKeysRequest),
62 SetCtrlPort(fidl_mlme::SetControlledPortRequest),
63 Start(fidl_mlme::StartRequest),
64 Stop(fidl_mlme::StopRequest),
65 GetIfaceStats(responder::Responder<fidl_mlme::GetIfaceStatsResponse>),
66 GetIfaceHistogramStats(responder::Responder<fidl_mlme::GetIfaceHistogramStatsResponse>),
67 GetSignalReport(responder::Responder<Result<fidl_stats::SignalReport, i32>>),
68 ListMinstrelPeers(responder::Responder<fidl_mlme::MinstrelListResponse>),
69 GetMinstrelStats(
70 fidl_mlme::MinstrelStatsRequest,
71 responder::Responder<fidl_mlme::MinstrelStatsResponse>,
72 ),
73 SaeHandshakeResp(fidl_mlme::SaeHandshakeResponse),
74 SaeFrameTx(fidl_mlme::SaeFrame),
75 WmmStatusReq,
76 FinalizeAssociation(fidl_mlme::NegotiatedCapabilities),
77 QueryDeviceInfo(responder::Responder<fidl_mlme::DeviceInfo>),
78 QueryMacSublayerSupport(responder::Responder<fidl_common::MacSublayerSupport>),
79 QuerySecuritySupport(responder::Responder<fidl_common::SecuritySupport>),
80 QuerySpectrumManagementSupport(responder::Responder<fidl_common::SpectrumManagementSupport>),
81 QueryTelemetrySupport(responder::Responder<Result<fidl_stats::TelemetrySupport, i32>>),
82 QueryApfPacketFilterSupport(
83 responder::Responder<Result<fidl_common::ApfPacketFilterSupport, i32>>,
84 ),
85 SetMacAddress(fidl_ieee80211::MacAddr, responder::Responder<Result<(), i32>>),
86 InstallApfPacketFilter(
87 fidl_mlme::MlmeInstallApfPacketFilterRequest,
88 responder::Responder<Result<(), i32>>,
89 ),
90 ReadApfPacketFilterData(
91 responder::Responder<Result<fidl_mlme::MlmeReadApfPacketFilterDataResponse, i32>>,
92 ),
93 SetApfPacketFilterEnabled(
94 fidl_mlme::MlmeSetApfPacketFilterEnabledRequest,
95 responder::Responder<Result<(), i32>>,
96 ),
97 GetApfPacketFilterEnabled(
98 responder::Responder<Result<fidl_mlme::MlmeGetApfPacketFilterEnabledResponse, i32>>,
99 ),
100 StartScheduledScan(
101 fidl_mlme::MlmeStartScheduledScanRequest,
102 responder::Responder<Result<(), i32>>,
103 ),
104 StopScheduledScan(
105 fidl_mlme::MlmeStopScheduledScanRequest,
106 responder::Responder<Result<(), i32>>,
107 ),
108 GetScheduledScanEnabled(
109 responder::Responder<Result<fidl_mlme::MlmeGetScheduledScanEnabledResponse, i32>>,
110 ),
111}
112
113impl MlmeRequest {
114 pub fn name(&self) -> &'static str {
115 match self {
116 Self::Scan(_) => "Scan",
117 Self::AuthResponse(_) => "AuthResponse",
118 Self::AssocResponse(_) => "AssocResponse",
119 Self::Connect(_) => "Connect",
120 Self::Reconnect(_) => "Reconnect",
121 Self::Roam(_) => "Roam",
122 Self::Deauthenticate(_) => "Deauthenticate",
123 Self::Disassociate(_) => "Disassociate",
124 Self::Eapol(_) => "Eapol",
125 Self::SetKeys(_) => "SetKeys",
126 Self::SetCtrlPort(_) => "SetCtrlPort",
127 Self::Start(_) => "Start",
128 Self::Stop(_) => "Stop",
129 Self::GetIfaceStats(_) => "GetIfaceStats",
130 Self::GetIfaceHistogramStats(_) => "GetIfaceHistogramStats",
131 Self::StartScheduledScan(..) => "StartScheduledScan",
132 Self::StopScheduledScan(..) => "StopScheduledScan",
133 Self::GetScheduledScanEnabled(_) => "GetScheduledScanEnabled",
134 Self::GetSignalReport(_) => "GetSignalReport",
135 Self::ListMinstrelPeers(_) => "ListMinstrelPeers",
136 Self::GetMinstrelStats(_, _) => "GetMinstrelStats",
137 Self::SaeHandshakeResp(_) => "SaeHandshakeResp",
138 Self::SaeFrameTx(_) => "SaeFrameTx",
139 Self::WmmStatusReq => "WmmStatusReq",
140 Self::FinalizeAssociation(_) => "FinalizeAssociation",
141 Self::QueryDeviceInfo(_) => "QueryDeviceInfo",
142 Self::QueryMacSublayerSupport(_) => "QueryMacSublayerSupport",
143 Self::QuerySecuritySupport(_) => "QuerySecuritySupport",
144 Self::QuerySpectrumManagementSupport(_) => "QuerySpectrumManagementSupport",
145 Self::QueryTelemetrySupport(_) => "QueryTelemetrySupport",
146 Self::QueryApfPacketFilterSupport(_) => "QueryApfPacketFilterSupport",
147 Self::SetMacAddress(..) => "SetMacAddress",
148 Self::InstallApfPacketFilter(..) => "InstallApfPacketFilter",
149 Self::ReadApfPacketFilterData(_) => "ReadApfPacketFilterData",
150 Self::SetApfPacketFilterEnabled(..) => "SetApfPacketFilterEnabled",
151 Self::GetApfPacketFilterEnabled(_) => "GetApfPacketFilterEnabled",
152 }
153 }
154}
155
156pub trait Station {
157 type Event;
158
159 fn on_mlme_event(&mut self, event: fidl_mlme::MlmeEvent);
160 fn on_timeout(&mut self, timed_event: timer::Event<Self::Event>);
161}
162
163pub type MlmeStream = mpsc::UnboundedReceiver<MlmeRequest>;
164pub type MlmeEventStream = mpsc::UnboundedReceiver<MlmeEvent>;
165pub type MlmeSink = UnboundedSink<MlmeRequest>;
166pub type MlmeEventSink = UnboundedSink<MlmeEvent>;
167
168pub mod responder {
169 use futures::channel::oneshot;
170
171 #[derive(Debug)]
172 pub struct Responder<T>(oneshot::Sender<T>);
173
174 impl<T> Responder<T> {
175 pub fn new() -> (Self, oneshot::Receiver<T>) {
176 let (sender, receiver) = oneshot::channel();
177 (Responder(sender), receiver)
178 }
179
180 pub fn respond(self, result: T) {
181 #[allow(
182 clippy::unnecessary_lazy_evaluations,
183 reason = "mass allow for https://fxbug.dev/381896734"
184 )]
185 self.0.send(result).unwrap_or_else(|_| ());
186 }
187 }
188}
189
190fn mlme_event_name(event: &MlmeEvent) -> &str {
192 match event {
193 MlmeEvent::OnScanResult { .. } => "OnScanResult",
194 MlmeEvent::OnScanEnd { .. } => "OnScanEnd",
195 MlmeEvent::ConnectConf { .. } => "ConnectConf",
196 MlmeEvent::RoamConf { .. } => "RoamConf",
197 MlmeEvent::RoamStartInd { .. } => "RoamStartInd",
198 MlmeEvent::RoamResultInd { .. } => "RoamResultInd",
199 MlmeEvent::AuthenticateInd { .. } => "AuthenticateInd",
200 MlmeEvent::DeauthenticateConf { .. } => "DeauthenticateConf",
201 MlmeEvent::DeauthenticateInd { .. } => "DeauthenticateInd",
202 MlmeEvent::AssociateInd { .. } => "AssociateInd",
203 MlmeEvent::DisassociateConf { .. } => "DisassociateConf",
204 MlmeEvent::DisassociateInd { .. } => "DisassociateInd",
205 MlmeEvent::SetKeysConf { .. } => "SetKeysConf",
206 MlmeEvent::StartConf { .. } => "StartConf",
207 MlmeEvent::StopConf { .. } => "StopConf",
208 MlmeEvent::EapolConf { .. } => "EapolConf",
209 MlmeEvent::SignalReport { .. } => "SignalReport",
210 MlmeEvent::EapolInd { .. } => "EapolInd",
211 MlmeEvent::RelayCapturedFrame { .. } => "RelayCapturedFrame",
212 MlmeEvent::OnChannelSwitched { .. } => "OnChannelSwitched",
213 MlmeEvent::OnPmkAvailable { .. } => "OnPmkAvailable",
214 MlmeEvent::OnSaeHandshakeInd { .. } => "OnSaeHandshakeInd",
215 MlmeEvent::OnSaeFrameRx { .. } => "OnSaeFrameRx",
216 MlmeEvent::OnWmmStatusResp { .. } => "OnWmmStatusResp",
217 MlmeEvent::OnScheduledScanMatchesAvailable { .. } => "OnScheduledScanMatchesAvailable",
218 MlmeEvent::OnScheduledScanStoppedByFirmware { .. } => "OnScheduledScanStoppedByFirmware",
219 }
220}
221
222#[derive(Debug, Error)]
223pub enum Error {
224 #[error("scan end while not scanning")]
225 ScanEndNotScanning,
226 #[error("scan end with wrong txn id")]
227 ScanEndWrongTxnId,
228 #[error("scan result while not scanning")]
229 ScanResultNotScanning,
230 #[error("scan result with wrong txn id")]
231 ScanResultWrongTxnId,
232}