use crate::ie;
use anyhow::format_err;
use std::fmt;
use {banjo_fuchsia_wlan_common as banjo_common, fidl_fuchsia_wlan_common as fidl_common};
pub type MHz = u16;
pub const BASE_FREQ_2GHZ: MHz = 2407;
pub const BASE_FREQ_5GHZ: MHz = 5000;
pub const INVALID_CHAN_IDX: u8 = 0;
#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
pub enum Cbw {
Cbw20,
Cbw40, Cbw40Below,
Cbw80,
Cbw160,
Cbw80P80 { secondary80: u8 },
}
impl Cbw {
pub fn to_fidl(&self) -> (fidl_common::ChannelBandwidth, u8) {
match self {
Cbw::Cbw20 => (fidl_common::ChannelBandwidth::Cbw20, 0),
Cbw::Cbw40 => (fidl_common::ChannelBandwidth::Cbw40, 0),
Cbw::Cbw40Below => (fidl_common::ChannelBandwidth::Cbw40Below, 0),
Cbw::Cbw80 => (fidl_common::ChannelBandwidth::Cbw80, 0),
Cbw::Cbw160 => (fidl_common::ChannelBandwidth::Cbw160, 0),
Cbw::Cbw80P80 { secondary80 } => {
(fidl_common::ChannelBandwidth::Cbw80P80, *secondary80)
}
}
}
pub fn to_banjo(&self) -> (banjo_common::ChannelBandwidth, u8) {
match self {
Cbw::Cbw20 => (banjo_common::ChannelBandwidth::CBW20, 0),
Cbw::Cbw40 => (banjo_common::ChannelBandwidth::CBW40, 0),
Cbw::Cbw40Below => (banjo_common::ChannelBandwidth::CBW40BELOW, 0),
Cbw::Cbw80 => (banjo_common::ChannelBandwidth::CBW80, 0),
Cbw::Cbw160 => (banjo_common::ChannelBandwidth::CBW160, 0),
Cbw::Cbw80P80 { secondary80 } => {
(banjo_common::ChannelBandwidth::CBW80P80, *secondary80)
}
}
}
pub fn from_fidl(
fidl_cbw: fidl_common::ChannelBandwidth,
fidl_secondary80: u8,
) -> Result<Self, anyhow::Error> {
match fidl_cbw {
fidl_common::ChannelBandwidth::Cbw20 => Ok(Cbw::Cbw20),
fidl_common::ChannelBandwidth::Cbw40 => Ok(Cbw::Cbw40),
fidl_common::ChannelBandwidth::Cbw40Below => Ok(Cbw::Cbw40Below),
fidl_common::ChannelBandwidth::Cbw80 => Ok(Cbw::Cbw80),
fidl_common::ChannelBandwidth::Cbw160 => Ok(Cbw::Cbw160),
fidl_common::ChannelBandwidth::Cbw80P80 => {
Ok(Cbw::Cbw80P80 { secondary80: fidl_secondary80 })
}
fidl_common::ChannelBandwidthUnknown!() => {
Err(format_err!("Unknown channel bandwidth from fidl: {:?}", fidl_cbw))
}
}
}
}
#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
pub struct Channel {
pub primary: u8,
pub cbw: Cbw,
}
impl fmt::Display for Cbw {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Cbw::Cbw20 => write!(f, ""), Cbw::Cbw40 => write!(f, "+"), Cbw::Cbw40Below => write!(f, "-"), Cbw::Cbw80 => write!(f, "V"), Cbw::Cbw160 => write!(f, "W"), Cbw::Cbw80P80 { secondary80 } => write!(f, "+{}P", secondary80), }
}
}
impl fmt::Display for Channel {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}{}", self.primary, self.cbw)
}
}
impl Channel {
pub fn new(primary: u8, cbw: Cbw) -> Self {
Channel { primary, cbw }
}
fn is_primary_2ghz(&self) -> bool {
let p = self.primary;
p >= 1 && p <= 14
}
fn is_primary_5ghz(&self) -> bool {
let p = self.primary;
match p {
36..=64 => (p - 36) % 4 == 0,
100..=144 => (p - 100) % 4 == 0,
149..=165 => (p - 149) % 4 == 0,
_ => false,
}
}
fn get_band_start_freq(&self) -> Result<MHz, anyhow::Error> {
if self.is_primary_2ghz() {
Ok(BASE_FREQ_2GHZ)
} else if self.is_primary_5ghz() {
Ok(BASE_FREQ_5GHZ)
} else {
return Err(format_err!("cannot get band start freq for channel {}", self));
}
}
fn get_center_chan_idx(&self) -> Result<u8, anyhow::Error> {
if !(self.is_primary_2ghz() || self.is_primary_5ghz()) {
return Err(format_err!(
"cannot get center channel index for an invalid primary channel {}",
self
));
}
let p = self.primary;
match self.cbw {
Cbw::Cbw20 => Ok(p),
Cbw::Cbw40 => Ok(p + 2),
Cbw::Cbw40Below => Ok(p - 2),
Cbw::Cbw80 | Cbw::Cbw80P80 { .. } => match p {
36..=48 => Ok(42),
52..=64 => Ok(58),
100..=112 => Ok(106),
116..=128 => Ok(122),
132..=144 => Ok(138),
148..=161_ => Ok(155),
_ => {
return Err(format_err!(
"cannot get center channel index for invalid channel {}",
self
))
}
},
Cbw::Cbw160 => {
match p {
36..=64 => Ok(50),
100..=128 => Ok(114),
_ => {
return Err(format_err!(
"cannot get center channel index for invalid channel {}",
self
))
}
}
}
}
}
pub fn get_center_freq(&self) -> Result<MHz, anyhow::Error> {
let start_freq = self.get_band_start_freq()?;
let center_chan_idx = self.get_center_chan_idx()?;
let spacing: MHz = 5;
Ok(start_freq + spacing * center_chan_idx as u16)
}
pub fn is_valid_in_us(&self) -> bool {
if self.is_primary_2ghz() {
self.is_valid_2ghz_in_us()
} else if self.is_primary_5ghz() {
self.is_valid_5ghz_in_us()
} else {
false
}
}
fn is_valid_2ghz_in_us(&self) -> bool {
if !self.is_primary_2ghz() {
return false;
}
let p = self.primary;
match self.cbw {
Cbw::Cbw20 => p <= 11,
Cbw::Cbw40 => p <= 7,
Cbw::Cbw40Below => p >= 5,
_ => false,
}
}
fn is_valid_5ghz_in_us(&self) -> bool {
if !self.is_primary_5ghz() {
return false;
}
let p = self.primary;
match self.cbw {
Cbw::Cbw20 => true,
Cbw::Cbw40 => p != 165 && (p % 8) == (if p <= 144 { 4 } else { 5 }),
Cbw::Cbw40Below => p != 165 && (p % 8) == (if p <= 144 { 0 } else { 1 }),
Cbw::Cbw80 => p != 165,
Cbw::Cbw160 => p < 132,
Cbw::Cbw80P80 { secondary80 } => {
if p == 165 {
return false;
}
let valid_secondary80: [u8; 6] = [42, 58, 106, 122, 138, 155];
if !valid_secondary80.contains(&secondary80) {
return false;
}
let ccfs0 = match self.get_center_chan_idx() {
Ok(v) => v,
Err(_) => return false,
};
let ccfs1 = secondary80;
let gap = (ccfs0 as i16 - ccfs1 as i16).abs();
gap > 16
}
}
}
pub fn is_2ghz(&self) -> bool {
self.is_primary_2ghz()
}
pub fn is_5ghz(&self) -> bool {
self.is_primary_5ghz()
}
#[allow(dead_code)]
fn is_unii1(&self) -> bool {
let p = self.primary;
p >= 32 && p <= 50
}
fn is_unii2a(&self) -> bool {
let p = self.primary;
p >= 50 && p <= 68
}
fn is_unii2c(&self) -> bool {
let p = self.primary;
p >= 96 && p <= 144
}
#[allow(dead_code)]
fn is_unii3(&self) -> bool {
let p = self.primary;
p >= 138 && p <= 165
}
pub fn is_dfs(&self) -> bool {
self.is_unii2a() || self.is_unii2c()
}
}
impl From<Channel> for fidl_common::WlanChannel {
fn from(channel: Channel) -> fidl_common::WlanChannel {
fidl_common::WlanChannel::from(&channel)
}
}
impl From<&Channel> for fidl_common::WlanChannel {
fn from(channel: &Channel) -> fidl_common::WlanChannel {
let (cbw, secondary80) = channel.cbw.to_fidl();
fidl_common::WlanChannel { primary: channel.primary, cbw, secondary80 }
}
}
impl TryFrom<fidl_common::WlanChannel> for Channel {
type Error = anyhow::Error;
fn try_from(fidl_channel: fidl_common::WlanChannel) -> Result<Channel, Self::Error> {
Channel::try_from(&fidl_channel)
}
}
impl TryFrom<&fidl_common::WlanChannel> for Channel {
type Error = anyhow::Error;
fn try_from(fidl_channel: &fidl_common::WlanChannel) -> Result<Channel, Self::Error> {
Ok(Channel {
primary: fidl_channel.primary,
cbw: Cbw::from_fidl(fidl_channel.cbw, fidl_channel.secondary80)?,
})
}
}
impl From<Channel> for banjo_common::WlanChannel {
fn from(channel: Channel) -> banjo_common::WlanChannel {
let (cbw, secondary80) = channel.cbw.to_banjo();
banjo_common::WlanChannel { primary: channel.primary, cbw, secondary80 }
}
}
impl From<&Channel> for banjo_common::WlanChannel {
fn from(channel: &Channel) -> banjo_common::WlanChannel {
let (cbw, secondary80) = channel.cbw.to_banjo();
banjo_common::WlanChannel { primary: channel.primary, cbw, secondary80 }
}
}
pub fn derive_channel(
rx_primary_channel: u8,
dsss_channel: Option<u8>,
ht_op: Option<ie::HtOperation>,
vht_op: Option<ie::VhtOperation>,
) -> fidl_common::WlanChannel {
let primary = ht_op
.as_ref()
.map(|ht_op| ht_op.primary_channel)
.or(dsss_channel)
.unwrap_or(rx_primary_channel);
let ht_op_cbw = ht_op.map(|ht_op| ht_op.ht_op_info.sta_chan_width());
let vht_cbw_and_segs =
vht_op.map(|vht_op| (vht_op.vht_cbw, vht_op.center_freq_seg0, vht_op.center_freq_seg1));
let (cbw, secondary80) = match ht_op_cbw {
Some(ie::StaChanWidth::ANY) => {
let sec_chan_offset = ht_op.unwrap().ht_op_info.secondary_chan_offset();
derive_wide_channel_bandwidth(vht_cbw_and_segs, sec_chan_offset)
}
_ => Cbw::Cbw20,
}
.to_fidl();
fidl_common::WlanChannel { primary, cbw, secondary80 }
}
pub fn derive_wide_channel_bandwidth(
vht_cbw_and_segs: Option<(ie::VhtChannelBandwidth, u8, u8)>,
sec_chan_offset: ie::SecChanOffset,
) -> Cbw {
use ie::VhtChannelBandwidth as Vcb;
match vht_cbw_and_segs {
Some((Vcb::CBW_80_160_80P80, _, 0)) => Cbw::Cbw80,
Some((Vcb::CBW_80_160_80P80, seg0, seg1)) if abs_sub(seg0, seg1) == 8 => Cbw::Cbw160,
Some((Vcb::CBW_80_160_80P80, seg0, seg1)) if abs_sub(seg0, seg1) > 16 => {
Cbw::Cbw80P80 { secondary80: seg1 }
}
_ => match sec_chan_offset {
ie::SecChanOffset::SECONDARY_ABOVE => Cbw::Cbw40,
ie::SecChanOffset::SECONDARY_BELOW => Cbw::Cbw40Below,
ie::SecChanOffset::SECONDARY_NONE | _ => Cbw::Cbw20,
},
}
}
fn abs_sub(v1: u8, v2: u8) -> u8 {
if v2 >= v1 {
v2 - v1
} else {
v1 - v2
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn fmt_display() {
let mut c = Channel::new(100, Cbw::Cbw40);
assert_eq!(format!("{}", c), "100+");
c.cbw = Cbw::Cbw160;
assert_eq!(format!("{}", c), "100W");
c.cbw = Cbw::Cbw80P80 { secondary80: 200 };
assert_eq!(format!("{}", c), "100+200P");
}
#[test]
fn test_is_primary_2ghz_or_5ghz() {
assert!(Channel::new(1, Cbw::Cbw160).is_primary_2ghz());
assert!(!Channel::new(1, Cbw::Cbw160).is_primary_5ghz());
assert!(Channel::new(12, Cbw::Cbw160).is_primary_2ghz());
assert!(!Channel::new(12, Cbw::Cbw160).is_primary_5ghz());
assert!(!Channel::new(36, Cbw::Cbw160).is_primary_2ghz());
assert!(Channel::new(36, Cbw::Cbw160).is_primary_5ghz());
assert!(!Channel::new(37, Cbw::Cbw160).is_primary_2ghz());
assert!(!Channel::new(37, Cbw::Cbw160).is_primary_5ghz());
assert!(!Channel::new(165, Cbw::Cbw160).is_primary_2ghz());
assert!(Channel::new(165, Cbw::Cbw160).is_primary_5ghz());
assert!(!Channel::new(166, Cbw::Cbw160).is_primary_2ghz());
assert!(!Channel::new(166, Cbw::Cbw160).is_primary_5ghz());
}
#[test]
fn test_band_start_freq() {
assert_eq!(BASE_FREQ_2GHZ, Channel::new(1, Cbw::Cbw20).get_band_start_freq().unwrap());
assert_eq!(BASE_FREQ_5GHZ, Channel::new(100, Cbw::Cbw20).get_band_start_freq().unwrap());
assert!(Channel::new(15, Cbw::Cbw20).get_band_start_freq().is_err());
assert!(Channel::new(200, Cbw::Cbw20).get_band_start_freq().is_err());
}
#[test]
fn test_get_center_chan_idx() {
assert!(Channel::new(1, Cbw::Cbw80).get_center_chan_idx().is_err());
assert_eq!(9, Channel::new(11, Cbw::Cbw40Below).get_center_chan_idx().unwrap());
assert_eq!(8, Channel::new(6, Cbw::Cbw40).get_center_chan_idx().unwrap());
assert_eq!(36, Channel::new(36, Cbw::Cbw20).get_center_chan_idx().unwrap());
assert_eq!(38, Channel::new(36, Cbw::Cbw40).get_center_chan_idx().unwrap());
assert_eq!(42, Channel::new(36, Cbw::Cbw80).get_center_chan_idx().unwrap());
assert_eq!(50, Channel::new(36, Cbw::Cbw160).get_center_chan_idx().unwrap());
assert_eq!(
42,
Channel::new(36, Cbw::Cbw80P80 { secondary80: 155 }).get_center_chan_idx().unwrap()
);
}
#[test]
fn test_get_center_freq() {
assert_eq!(2412 as MHz, Channel::new(1, Cbw::Cbw20).get_center_freq().unwrap());
assert_eq!(2437 as MHz, Channel::new(6, Cbw::Cbw20).get_center_freq().unwrap());
assert_eq!(2447 as MHz, Channel::new(6, Cbw::Cbw40).get_center_freq().unwrap());
assert_eq!(2427 as MHz, Channel::new(6, Cbw::Cbw40Below).get_center_freq().unwrap());
assert_eq!(5180 as MHz, Channel::new(36, Cbw::Cbw20).get_center_freq().unwrap());
assert_eq!(5190 as MHz, Channel::new(36, Cbw::Cbw40).get_center_freq().unwrap());
assert_eq!(5210 as MHz, Channel::new(36, Cbw::Cbw80).get_center_freq().unwrap());
assert_eq!(5250 as MHz, Channel::new(36, Cbw::Cbw160).get_center_freq().unwrap());
assert_eq!(
5210 as MHz,
Channel::new(36, Cbw::Cbw80P80 { secondary80: 155 }).get_center_freq().unwrap()
);
}
#[test]
fn test_valid_us_combo() {
assert!(Channel::new(1, Cbw::Cbw20).is_valid_in_us());
assert!(Channel::new(1, Cbw::Cbw40).is_valid_in_us());
assert!(Channel::new(5, Cbw::Cbw40Below).is_valid_in_us());
assert!(Channel::new(6, Cbw::Cbw20).is_valid_in_us());
assert!(Channel::new(6, Cbw::Cbw40).is_valid_in_us());
assert!(Channel::new(6, Cbw::Cbw40Below).is_valid_in_us());
assert!(Channel::new(7, Cbw::Cbw40).is_valid_in_us());
assert!(Channel::new(11, Cbw::Cbw20).is_valid_in_us());
assert!(Channel::new(11, Cbw::Cbw40Below).is_valid_in_us());
assert!(Channel::new(36, Cbw::Cbw20).is_valid_in_us());
assert!(Channel::new(36, Cbw::Cbw40).is_valid_in_us());
assert!(Channel::new(36, Cbw::Cbw160).is_valid_in_us());
assert!(Channel::new(40, Cbw::Cbw20).is_valid_in_us());
assert!(Channel::new(40, Cbw::Cbw40Below).is_valid_in_us());
assert!(Channel::new(40, Cbw::Cbw160).is_valid_in_us());
assert!(Channel::new(36, Cbw::Cbw80P80 { secondary80: 155 }).is_valid_in_us());
assert!(Channel::new(40, Cbw::Cbw80P80 { secondary80: 155 }).is_valid_in_us());
assert!(Channel::new(161, Cbw::Cbw80P80 { secondary80: 42 }).is_valid_in_us());
}
#[test]
fn test_invalid_us_combo() {
assert!(!Channel::new(1, Cbw::Cbw40Below).is_valid_in_us());
assert!(!Channel::new(4, Cbw::Cbw40Below).is_valid_in_us());
assert!(!Channel::new(8, Cbw::Cbw40).is_valid_in_us());
assert!(!Channel::new(11, Cbw::Cbw40).is_valid_in_us());
assert!(!Channel::new(6, Cbw::Cbw80).is_valid_in_us());
assert!(!Channel::new(6, Cbw::Cbw160).is_valid_in_us());
assert!(!Channel::new(6, Cbw::Cbw80P80 { secondary80: 155 }).is_valid_in_us());
assert!(!Channel::new(36, Cbw::Cbw40Below).is_valid_in_us());
assert!(!Channel::new(36, Cbw::Cbw80P80 { secondary80: 58 }).is_valid_in_us());
assert!(!Channel::new(40, Cbw::Cbw40).is_valid_in_us());
assert!(!Channel::new(40, Cbw::Cbw80P80 { secondary80: 42 }).is_valid_in_us());
assert!(!Channel::new(165, Cbw::Cbw80).is_valid_in_us());
assert!(!Channel::new(165, Cbw::Cbw80P80 { secondary80: 42 }).is_valid_in_us());
}
#[test]
fn test_is_2ghz_or_5ghz() {
assert!(Channel::new(1, Cbw::Cbw20).is_2ghz());
assert!(!Channel::new(1, Cbw::Cbw20).is_5ghz());
assert!(Channel::new(13, Cbw::Cbw20).is_2ghz());
assert!(!Channel::new(13, Cbw::Cbw20).is_5ghz());
assert!(Channel::new(36, Cbw::Cbw20).is_5ghz());
assert!(!Channel::new(36, Cbw::Cbw20).is_2ghz());
}
#[test]
fn test_is_dfs() {
assert!(!Channel::new(1, Cbw::Cbw20).is_dfs());
assert!(!Channel::new(36, Cbw::Cbw20).is_dfs());
assert!(Channel::new(50, Cbw::Cbw20).is_dfs());
assert!(Channel::new(144, Cbw::Cbw20).is_dfs());
assert!(!Channel::new(149, Cbw::Cbw20).is_dfs());
}
#[test]
fn test_convert_fidl_channel() {
let mut f = fidl_common::WlanChannel::from(Channel::new(1, Cbw::Cbw20));
assert!(
f.primary == 1 && f.cbw == fidl_common::ChannelBandwidth::Cbw20 && f.secondary80 == 0
);
f = Channel::new(36, Cbw::Cbw80P80 { secondary80: 155 }).into();
assert!(
f.primary == 36
&& f.cbw == fidl_common::ChannelBandwidth::Cbw80P80
&& f.secondary80 == 155
);
let mut c = Channel::try_from(fidl_common::WlanChannel {
primary: 11,
cbw: fidl_common::ChannelBandwidth::Cbw40Below,
secondary80: 123,
})
.unwrap();
assert!(c.primary == 11 && c.cbw == Cbw::Cbw40Below);
c = fidl_common::WlanChannel {
primary: 149,
cbw: fidl_common::ChannelBandwidth::Cbw80P80,
secondary80: 42,
}
.try_into()
.unwrap();
assert!(c.primary == 149 && c.cbw == Cbw::Cbw80P80 { secondary80: 42 });
let r = Channel::try_from(fidl_common::WlanChannel {
primary: 11,
cbw: fidl_common::ChannelBandwidth::unknown(),
secondary80: 123,
});
assert!(r.is_err());
}
const RX_PRIMARY_CHAN: u8 = 11;
const HT_PRIMARY_CHAN: u8 = 48;
#[test]
fn test_derive_channel_basic() {
let channel = derive_channel(RX_PRIMARY_CHAN, None, None, None);
assert_eq!(
channel,
fidl_common::WlanChannel {
primary: RX_PRIMARY_CHAN,
cbw: fidl_common::ChannelBandwidth::Cbw20,
secondary80: 0,
}
);
}
#[test]
fn test_derive_channel_with_dsss_param() {
let channel = derive_channel(RX_PRIMARY_CHAN, Some(6), None, None);
assert_eq!(
channel,
fidl_common::WlanChannel {
primary: 6,
cbw: fidl_common::ChannelBandwidth::Cbw20,
secondary80: 0
}
);
}
#[test]
fn test_derive_channel_with_ht_20mhz() {
let expected_channel = fidl_common::WlanChannel {
primary: HT_PRIMARY_CHAN,
cbw: fidl_common::ChannelBandwidth::Cbw20,
secondary80: 0,
};
let test_params = [
(ie::StaChanWidth::TWENTY_MHZ, ie::SecChanOffset::SECONDARY_NONE),
(ie::StaChanWidth::TWENTY_MHZ, ie::SecChanOffset::SECONDARY_ABOVE),
(ie::StaChanWidth::TWENTY_MHZ, ie::SecChanOffset::SECONDARY_BELOW),
(ie::StaChanWidth::ANY, ie::SecChanOffset::SECONDARY_NONE),
];
for (ht_width, sec_chan_offset) in test_params.iter() {
let ht_op = ht_op(HT_PRIMARY_CHAN, *ht_width, *sec_chan_offset);
let channel = derive_channel(RX_PRIMARY_CHAN, Some(6), Some(ht_op), None);
assert_eq!(channel, expected_channel);
}
}
#[test]
fn test_derive_channel_with_ht_40mhz() {
let ht_op =
ht_op(HT_PRIMARY_CHAN, ie::StaChanWidth::ANY, ie::SecChanOffset::SECONDARY_ABOVE);
let channel = derive_channel(RX_PRIMARY_CHAN, Some(6), Some(ht_op), None);
assert_eq!(
channel,
fidl_common::WlanChannel {
primary: HT_PRIMARY_CHAN,
cbw: fidl_common::ChannelBandwidth::Cbw40,
secondary80: 0,
}
);
}
#[test]
fn test_derive_channel_with_ht_40mhz_below() {
let ht_op =
ht_op(HT_PRIMARY_CHAN, ie::StaChanWidth::ANY, ie::SecChanOffset::SECONDARY_BELOW);
let channel = derive_channel(RX_PRIMARY_CHAN, Some(6), Some(ht_op), None);
assert_eq!(
channel,
fidl_common::WlanChannel {
primary: HT_PRIMARY_CHAN,
cbw: fidl_common::ChannelBandwidth::Cbw40Below,
secondary80: 0,
}
);
}
#[test]
fn test_derive_channel_with_vht_80mhz() {
let ht_op =
ht_op(HT_PRIMARY_CHAN, ie::StaChanWidth::ANY, ie::SecChanOffset::SECONDARY_ABOVE);
let vht_op = vht_op(ie::VhtChannelBandwidth::CBW_80_160_80P80, 8, 0);
let channel = derive_channel(RX_PRIMARY_CHAN, Some(6), Some(ht_op), Some(vht_op));
assert_eq!(
channel,
fidl_common::WlanChannel {
primary: HT_PRIMARY_CHAN,
cbw: fidl_common::ChannelBandwidth::Cbw80,
secondary80: 0,
}
);
}
#[test]
fn test_derive_channel_with_vht_160mhz() {
let ht_op =
ht_op(HT_PRIMARY_CHAN, ie::StaChanWidth::ANY, ie::SecChanOffset::SECONDARY_ABOVE);
let vht_op = vht_op(ie::VhtChannelBandwidth::CBW_80_160_80P80, 0, 8);
let channel = derive_channel(RX_PRIMARY_CHAN, Some(6), Some(ht_op), Some(vht_op));
assert_eq!(
channel,
fidl_common::WlanChannel {
primary: HT_PRIMARY_CHAN,
cbw: fidl_common::ChannelBandwidth::Cbw160,
secondary80: 0,
}
);
}
#[test]
fn test_derive_channel_with_vht_80plus80mhz() {
let ht_op =
ht_op(HT_PRIMARY_CHAN, ie::StaChanWidth::ANY, ie::SecChanOffset::SECONDARY_ABOVE);
let vht_op = vht_op(ie::VhtChannelBandwidth::CBW_80_160_80P80, 18, 1);
let channel = derive_channel(RX_PRIMARY_CHAN, Some(6), Some(ht_op), Some(vht_op));
assert_eq!(
channel,
fidl_common::WlanChannel {
primary: HT_PRIMARY_CHAN,
cbw: fidl_common::ChannelBandwidth::Cbw80P80,
secondary80: 1,
}
);
}
#[test]
fn test_derive_channel_none() {
let channel = derive_channel(8, None, None, None);
assert_eq!(
channel,
fidl_common::WlanChannel {
primary: 8,
cbw: fidl_common::ChannelBandwidth::Cbw20,
secondary80: 0,
}
);
}
#[test]
fn test_derive_channel_no_rx_primary() {
let channel = derive_channel(8, Some(6), None, None);
assert_eq!(
channel,
fidl_common::WlanChannel {
primary: 6,
cbw: fidl_common::ChannelBandwidth::Cbw20,
secondary80: 0,
}
)
}
fn ht_op(
primary_channel: u8,
chan_width: ie::StaChanWidth,
offset: ie::SecChanOffset,
) -> ie::HtOperation {
let ht_op_info =
ie::HtOpInfo::new().with_sta_chan_width(chan_width).with_secondary_chan_offset(offset);
ie::HtOperation { primary_channel, ht_op_info, basic_ht_mcs_set: ie::SupportedMcsSet(0) }
}
fn vht_op(vht_cbw: ie::VhtChannelBandwidth, seg0: u8, seg1: u8) -> ie::VhtOperation {
ie::VhtOperation {
vht_cbw,
center_freq_seg0: seg0,
center_freq_seg1: seg1,
basic_mcs_nss: ie::VhtMcsNssMap(0),
}
}
}