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