1use crate::WlanSoftmacBandCapabilityExt as _;
6use anyhow::format_err;
7use std::fmt::Display;
8use {
9 fidl_fuchsia_wlan_ieee80211 as fidl_ieee80211, fidl_fuchsia_wlan_mlme as fidl_mlme,
10 fidl_fuchsia_wlan_softmac as fidl_softmac,
11};
12
13#[macro_export]
14macro_rules! zeroed_array_from_prefix {
15 ($slice:expr, $size:expr $(,)?) => {{
16 assert!($slice.len() <= $size);
17 let mut a = [0; $size];
18 a[..$slice.len()].clone_from_slice(&$slice);
19 a
20 }};
21}
22
23pub fn softmac_key_configuration_from_mlme(
24 key_descriptor: fidl_mlme::SetKeyDescriptor,
25) -> fidl_softmac::WlanKeyConfiguration {
26 fidl_softmac::WlanKeyConfiguration {
27 protection: Some(fidl_softmac::WlanProtection::RxTx),
28 cipher_oui: Some(key_descriptor.cipher_suite_oui),
29 cipher_type: Some(fidl_ieee80211::CipherSuiteType::into_primitive(
30 key_descriptor.cipher_suite_type,
31 ) as u8),
32 key_type: Some(match key_descriptor.key_type {
33 fidl_mlme::KeyType::Pairwise => fidl_ieee80211::KeyType::Pairwise,
34 fidl_mlme::KeyType::PeerKey => fidl_ieee80211::KeyType::Peer,
35 fidl_mlme::KeyType::Igtk => fidl_ieee80211::KeyType::Igtk,
36 fidl_mlme::KeyType::Group => fidl_ieee80211::KeyType::Group,
37 }),
38 peer_addr: Some(key_descriptor.address),
39 key_idx: Some(key_descriptor.key_id as u8),
40 key: Some(key_descriptor.key),
41 rsc: Some(key_descriptor.rsc),
42 ..Default::default()
43 }
44}
45
46pub fn mlme_band_cap_from_softmac(
47 band_cap: fidl_softmac::WlanSoftmacBandCapability,
48) -> Result<fidl_mlme::BandCapability, anyhow::Error> {
49 fn required<T>(field: Option<T>, name: impl Display) -> Result<T, anyhow::Error> {
50 field.ok_or_else(|| {
51 format_err!("Required band capability field unset in SoftMAC driver FIDL: `{}`.", name)
52 })
53 }
54
55 fn predicated<T>(predicate: Option<bool>, field: Option<T>) -> Option<T> {
62 predicate.unwrap_or(false).then_some(field).flatten()
64 }
65
66 Ok(fidl_mlme::BandCapability {
67 band: required(band_cap.band, "band")?,
68 basic_rates: required(band_cap.basic_rates(), "basic_rates")?.into(),
69 operating_channels: required(band_cap.operating_channels(), "operating_channels")?.into(),
70 ht_cap: predicated(band_cap.ht_supported, band_cap.ht_caps).map(Box::new),
71 vht_cap: predicated(band_cap.vht_supported, band_cap.vht_caps).map(Box::new),
72 })
73}
74
75pub fn mlme_device_info_from_softmac(
76 query_response: fidl_softmac::WlanSoftmacQueryResponse,
77) -> Result<fidl_mlme::DeviceInfo, anyhow::Error> {
78 fn required<T>(field: Option<T>, name: impl Display) -> Result<T, anyhow::Error> {
79 field.ok_or_else(|| {
80 format_err!("Required query field unset in SoftMAC driver FIDL: `{}`.", name)
81 })
82 }
83
84 let band_caps = query_response
85 .band_caps
86 .as_ref()
87 .map(|band_caps| {
88 band_caps.iter().cloned().map(mlme_band_cap_from_softmac).collect::<Result<Vec<_>, _>>()
89 })
90 .transpose()?;
91 Ok(fidl_mlme::DeviceInfo {
92 sta_addr: required(query_response.sta_addr, "sta_addr")?,
93 role: required(query_response.mac_role, "mac_role")?,
94 bands: required(band_caps, "band_caps")?,
95 qos_capable: false,
96 softmac_hardware_capability: required(
99 query_response.hardware_capability,
100 "hardware_capability",
101 )?,
102 })
103}
104
105pub fn get_rssi_dbm(rx_info: fidl_softmac::WlanRxInfo) -> Option<i8> {
106 if rx_info.valid_fields.contains(fidl_softmac::WlanRxInfoValid::RSSI) && rx_info.rssi_dbm != 0 {
107 Some(rx_info.rssi_dbm)
108 } else {
109 None
110 }
111}
112
113pub fn cssid_from_ssid_unchecked(ssid: &Vec<u8>) -> fidl_ieee80211::CSsid {
116 let mut cssid = fidl_ieee80211::CSsid {
117 len: ssid.len() as u8,
118 data: [0; fidl_ieee80211::MAX_SSID_BYTE_LEN as usize],
119 };
120 cssid.data[..ssid.len()].copy_from_slice(&ssid[..]);
122 cssid
123}
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128 use fidl_fuchsia_wlan_common as fidl_common;
129
130 fn empty_rx_info() -> fidl_softmac::WlanRxInfo {
131 fidl_softmac::WlanRxInfo {
132 rx_flags: fidl_softmac::WlanRxInfoFlags::empty(),
133 valid_fields: fidl_softmac::WlanRxInfoValid::empty(),
134 phy: fidl_common::WlanPhyType::Dsss,
135 data_rate: 0,
136 channel: fidl_common::WlanChannel {
137 primary: 0,
138 cbw: fidl_common::ChannelBandwidth::Cbw20,
139 secondary80: 0,
140 },
141 mcs: 0,
142 rssi_dbm: 0,
143 snr_dbh: 0,
144 }
145 }
146
147 #[test]
148 fn test_get_rssi_dbm_field_not_valid() {
149 let rx_info = fidl_softmac::WlanRxInfo {
150 valid_fields: fidl_softmac::WlanRxInfoValid::empty(),
151 rssi_dbm: 20,
152 ..empty_rx_info()
153 };
154 assert_eq!(get_rssi_dbm(rx_info), None);
155 }
156
157 #[test]
158 fn test_get_rssi_dbm_zero_dbm() {
159 let rx_info = fidl_softmac::WlanRxInfo {
160 valid_fields: fidl_softmac::WlanRxInfoValid::RSSI,
161 rssi_dbm: 0,
162 ..empty_rx_info()
163 };
164 assert_eq!(get_rssi_dbm(rx_info), None);
165 }
166
167 #[test]
168 fn test_get_rssi_dbm_all_good() {
169 let rx_info = fidl_softmac::WlanRxInfo {
170 valid_fields: fidl_softmac::WlanRxInfoValid::RSSI,
171 rssi_dbm: 20,
172 ..empty_rx_info()
173 };
174 assert_eq!(get_rssi_dbm(rx_info), Some(20));
175 }
176
177 #[test]
178 fn test_mlme_band_cap_from_softmac() {
179 let softmac_band_cap = fidl_softmac::WlanSoftmacBandCapability {
180 band: Some(fidl_ieee80211::WlanBand::TwoGhz),
181 basic_rates: Some(vec![
182 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c,
183 ]),
184 operating_channels: Some(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]),
185 ht_supported: Some(true),
186 ht_caps: Some(fidl_ieee80211::HtCapabilities {
187 bytes: [
188 0x63, 0x00, 0x17, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
191 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ],
197 }),
198 vht_supported: Some(false),
199 vht_caps: Some(fidl_ieee80211::VhtCapabilities { bytes: Default::default() }),
200 ..Default::default()
201 };
202 let mlme_band_cap = mlme_band_cap_from_softmac(softmac_band_cap)
203 .expect("failed to convert band capability");
204 assert_eq!(mlme_band_cap.band, fidl_ieee80211::WlanBand::TwoGhz);
205 assert_eq!(
206 mlme_band_cap.basic_rates,
207 vec![0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c]
208 );
209 assert_eq!(
210 mlme_band_cap.operating_channels,
211 vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
212 );
213 assert!(mlme_band_cap.ht_cap.is_some());
214 assert!(mlme_band_cap.vht_cap.is_none());
215 }
216}