1use crate::ie;
6use anyhow::format_err;
7use fidl_fuchsia_wlan_ieee80211 as fidl_ieee80211;
8use std::fmt;
9
10pub type MHz = u16;
17pub const BASE_FREQ_2GHZ: MHz = 2407;
18pub const BASE_FREQ_5GHZ: MHz = 5000;
19
20pub const INVALID_CHAN_IDX: u8 = 0;
21
22#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
26pub enum Bandwidth {
27 Cbw20,
28 Cbw40, Cbw40Below,
30 Cbw80,
31 Cbw160,
32 Cbw80P80 { vht_secondary_80_channel: u8 },
33}
34
35impl Bandwidth {
36 pub fn to_fidl(&self) -> (fidl_ieee80211::ChannelBandwidth, u8) {
38 match self {
39 Bandwidth::Cbw20 => (fidl_ieee80211::ChannelBandwidth::Cbw20, 0),
40 Bandwidth::Cbw40 => (fidl_ieee80211::ChannelBandwidth::Cbw40, 0),
41 Bandwidth::Cbw40Below => (fidl_ieee80211::ChannelBandwidth::Cbw40Below, 0),
42 Bandwidth::Cbw80 => (fidl_ieee80211::ChannelBandwidth::Cbw80, 0),
43 Bandwidth::Cbw160 => (fidl_ieee80211::ChannelBandwidth::Cbw160, 0),
44 Bandwidth::Cbw80P80 { vht_secondary_80_channel } => {
45 (fidl_ieee80211::ChannelBandwidth::Cbw80P80, *vht_secondary_80_channel)
46 }
47 }
48 }
49
50 pub fn from_fidl(
51 fidl_cbw: fidl_ieee80211::ChannelBandwidth,
52 fidl_vht_secondary_80_channel: u8,
53 ) -> Result<Self, anyhow::Error> {
54 match fidl_cbw {
55 fidl_ieee80211::ChannelBandwidth::Cbw20 => Ok(Bandwidth::Cbw20),
56 fidl_ieee80211::ChannelBandwidth::Cbw40 => Ok(Bandwidth::Cbw40),
57 fidl_ieee80211::ChannelBandwidth::Cbw40Below => Ok(Bandwidth::Cbw40Below),
58 fidl_ieee80211::ChannelBandwidth::Cbw80 => Ok(Bandwidth::Cbw80),
59 fidl_ieee80211::ChannelBandwidth::Cbw160 => Ok(Bandwidth::Cbw160),
60 fidl_ieee80211::ChannelBandwidth::Cbw80P80 => {
61 Ok(Bandwidth::Cbw80P80 { vht_secondary_80_channel: fidl_vht_secondary_80_channel })
62 }
63 fidl_ieee80211::ChannelBandwidthUnknown!() => {
64 Err(format_err!("Unknown channel bandwidth from fidl: {:?}", fidl_cbw))
65 }
66 }
67 }
68}
69
70#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
75pub struct Channel {
76 pub primary: u8,
77 pub bandwidth: Bandwidth,
78 pub band: fidl_ieee80211::WlanBand,
79}
80
81impl fmt::Display for Bandwidth {
83 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84 match self {
85 Bandwidth::Cbw20 => write!(f, ""), Bandwidth::Cbw40 => write!(f, "+"), Bandwidth::Cbw40Below => write!(f, "-"), Bandwidth::Cbw80 => write!(f, "V"), Bandwidth::Cbw160 => write!(f, "W"), Bandwidth::Cbw80P80 { vht_secondary_80_channel } => {
91 write!(f, "+{}P", vht_secondary_80_channel)
92 } }
94 }
95}
96
97impl fmt::Display for Channel {
98 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99 write!(f, "{}{} ({:?})", self.primary, self.bandwidth, self.band)
100 }
101}
102
103impl Channel {
104 pub const fn new(primary: u8, bandwidth: Bandwidth, band: fidl_ieee80211::WlanBand) -> Self {
105 Channel { primary, bandwidth, band }
106 }
107
108 fn get_band_start_freq(&self) -> Result<MHz, anyhow::Error> {
109 match self.band {
110 fidl_ieee80211::WlanBand::TwoGhz => Ok(BASE_FREQ_2GHZ),
111 fidl_ieee80211::WlanBand::FiveGhz => Ok(BASE_FREQ_5GHZ),
112 _ => Err(format_err!("cannot get band start freq for channel {}", self)),
113 }
114 }
115
116 fn get_center_chan_idx(&self) -> Result<u8, anyhow::Error> {
117 let is_valid = match self.band {
118 fidl_ieee80211::WlanBand::TwoGhz => (1..=14).contains(&self.primary),
119 fidl_ieee80211::WlanBand::FiveGhz => (36..=177).contains(&self.primary),
120 _ => false,
121 };
122 if !is_valid {
123 return Err(format_err!(
124 "cannot get center channel index for an invalid primary channel {}",
125 self
126 ));
127 }
128
129 let p = self.primary;
130 match self.bandwidth {
131 Bandwidth::Cbw20 => Ok(p),
132 Bandwidth::Cbw40 => {
133 p.checked_add(2).ok_or_else(|| format_err!("invalid channel for Cbw40: {}", p))
134 }
135 Bandwidth::Cbw40Below => p
136 .checked_sub(2)
137 .filter(|&res| res != INVALID_CHAN_IDX)
138 .ok_or_else(|| format_err!("invalid channel for Cbw40Below: {}", p)),
139 Bandwidth::Cbw80 | Bandwidth::Cbw80P80 { .. } => match p {
140 36..=48 => Ok(42),
141 52..=64 => Ok(58),
142 100..=112 => Ok(106),
143 116..=128 => Ok(122),
144 132..=144 => Ok(138),
145 149..=161 => Ok(155),
146 165..=177 => Ok(171),
147 _ => {
148 return Err(format_err!(
149 "cannot get center channel index for invalid channel {}",
150 self
151 ));
152 }
153 },
154 Bandwidth::Cbw160 => match p {
155 36..=64 => Ok(50),
156 100..=128 => Ok(114),
157 149..=177 => Ok(163),
158 _ => {
159 return Err(format_err!(
160 "cannot get center channel index for invalid channel {}",
161 self
162 ));
163 }
164 },
165 }
166 }
167
168 pub fn get_center_freq(&self) -> Result<MHz, anyhow::Error> {
171 let start_freq = self.get_band_start_freq()?;
173 let center_chan_idx = self.get_center_chan_idx()?;
174 let spacing: MHz = 5;
175 let offset = spacing
176 .checked_mul(center_chan_idx as u16)
177 .ok_or_else(|| format_err!("overflow computing channel spacing offset for {}", self))?;
178 start_freq
179 .checked_add(offset)
180 .ok_or_else(|| format_err!("overflow computing center frequency for {}", self))
181 }
182}
183
184impl Into<fidl_ieee80211::ChannelNumber> for Channel {
185 fn into(self) -> fidl_ieee80211::ChannelNumber {
186 fidl_ieee80211::ChannelNumber { band: self.band, number: self.primary }
187 }
188}
189impl Channel {
190 pub fn from_fidl(
191 fidl_channel: fidl_ieee80211::ChannelNumber,
192 fidl_cbw: fidl_ieee80211::ChannelBandwidth,
193 fidl_vht_secondary_80_channel: fidl_ieee80211::ChannelNumber,
194 ) -> Result<Self, anyhow::Error> {
195 if fidl_cbw == fidl_ieee80211::ChannelBandwidth::Cbw80P80 {
196 if fidl_vht_secondary_80_channel.band != fidl_channel.band {
197 return Err(format_err!(
198 "vht_secondary_80_channel band ({:?}) does not match primary band ({:?})",
199 fidl_vht_secondary_80_channel.band,
200 fidl_channel.band
201 ));
202 }
203 }
204 let cbw = Bandwidth::from_fidl(fidl_cbw, fidl_vht_secondary_80_channel.number)?;
205 Ok(Channel::new(fidl_channel.number, cbw, fidl_channel.band))
206 }
207}
208
209pub fn derive_channel(
216 rx_primary_channel: fidl_ieee80211::ChannelNumber,
217 dsss_channel: Option<u8>,
218 ht_op: Option<ie::HtOperation>,
219 vht_op: Option<ie::VhtOperation>,
220) -> Channel {
221 let primary = ht_op
222 .as_ref()
223 .map(|ht_op| ht_op.primary_channel)
224 .or(dsss_channel)
225 .unwrap_or(rx_primary_channel.number);
226
227 let ht_op_cbw = ht_op.map(|ht_op| ht_op.ht_op_info.sta_chan_width());
228 let vht_cbw_and_segs =
229 vht_op.map(|vht_op| (vht_op.vht_cbw, vht_op.center_freq_seg0, vht_op.center_freq_seg1));
230
231 let cbw = match ht_op_cbw {
232 Some(ie::StaChanWidth::ANY) => {
234 let sec_chan_offset = ht_op.unwrap().ht_op_info.secondary_chan_offset();
236 derive_wide_channel_bandwidth(vht_cbw_and_segs, sec_chan_offset)
237 }
238 _ => Bandwidth::Cbw20,
240 };
241
242 Channel::new(primary, cbw, rx_primary_channel.band)
243}
244
245pub fn derive_wide_channel_bandwidth(
253 vht_cbw_and_segs: Option<(ie::VhtChannelBandwidth, u8, u8)>,
254 sec_chan_offset: ie::SecChanOffset,
255) -> Bandwidth {
256 use ie::VhtChannelBandwidth as Vcb;
257 match vht_cbw_and_segs {
258 Some((Vcb::CBW_80_160_80P80, _, 0)) => Bandwidth::Cbw80,
259 Some((Vcb::CBW_80_160_80P80, seg0, seg1)) if seg0.abs_diff(seg1) == 8 => Bandwidth::Cbw160,
260 Some((Vcb::CBW_80_160_80P80, seg0, seg1)) if seg0.abs_diff(seg1) > 16 => {
261 Bandwidth::Cbw80P80 { vht_secondary_80_channel: seg1 }
263 }
264 _ => match sec_chan_offset {
268 ie::SecChanOffset::SECONDARY_ABOVE => Bandwidth::Cbw40,
269 ie::SecChanOffset::SECONDARY_BELOW => Bandwidth::Cbw40Below,
270 ie::SecChanOffset::SECONDARY_NONE | _ => Bandwidth::Cbw20,
271 },
272 }
273}
274
275pub fn primary_channel_from_freq(freq: u32) -> Option<u8> {
279 if (2412..=2472).contains(&freq) && (freq - 2412) % 5 == 0 {
281 Some(((freq - 2407) / 5) as u8)
282 } else if freq == 2484 {
284 Some(14)
285 } else if (5180..=5720).contains(&freq) && (freq - 5180) % 20 == 0 {
287 Some(((freq - 5000) / 5) as u8)
288 } else if (5745..=5865).contains(&freq) && (freq - 5745) % 20 == 0 {
290 Some(((freq - 5000) / 5) as u8)
291 } else {
292 None
293 }
294}
295
296#[cfg(test)]
297mod tests {
298 use super::*;
299 use fidl_ieee80211::WlanBand::{FiveGhz, TwoGhz};
300
301 fn rx_channel(number: u8, band: fidl_ieee80211::WlanBand) -> fidl_ieee80211::ChannelNumber {
302 fidl_ieee80211::ChannelNumber { band, number }
303 }
304
305 #[test]
306 fn fmt_display() {
307 let mut c = Channel::new(100, Bandwidth::Cbw40, FiveGhz);
308 assert_eq!(format!("{}", c), "100+ (FiveGhz)");
309 c.bandwidth = Bandwidth::Cbw160;
310 assert_eq!(format!("{}", c), "100W (FiveGhz)");
311 c.bandwidth = Bandwidth::Cbw80P80 { vht_secondary_80_channel: 200 };
312 assert_eq!(format!("{}", c), "100+200P (FiveGhz)");
313 }
314
315 #[test]
316 fn test_band_start_freq() {
317 assert_eq!(
318 BASE_FREQ_2GHZ,
319 Channel::new(1, Bandwidth::Cbw20, TwoGhz).get_band_start_freq().unwrap()
320 );
321 assert_eq!(
322 BASE_FREQ_5GHZ,
323 Channel::new(100, Bandwidth::Cbw20, FiveGhz).get_band_start_freq().unwrap()
324 );
325 }
326
327 #[test]
328 fn test_get_center_chan_idx() {
329 assert!(Channel::new(1, Bandwidth::Cbw80, TwoGhz).get_center_chan_idx().is_err());
330 assert_eq!(
331 9,
332 Channel::new(11, Bandwidth::Cbw40Below, TwoGhz).get_center_chan_idx().unwrap()
333 );
334 assert_eq!(8, Channel::new(6, Bandwidth::Cbw40, TwoGhz).get_center_chan_idx().unwrap());
335 assert_eq!(36, Channel::new(36, Bandwidth::Cbw20, FiveGhz).get_center_chan_idx().unwrap());
336 assert_eq!(38, Channel::new(36, Bandwidth::Cbw40, FiveGhz).get_center_chan_idx().unwrap());
337
338 assert_eq!(42, Channel::new(36, Bandwidth::Cbw80, FiveGhz).get_center_chan_idx().unwrap());
340 assert_eq!(42, Channel::new(48, Bandwidth::Cbw80, FiveGhz).get_center_chan_idx().unwrap());
341 assert_eq!(58, Channel::new(52, Bandwidth::Cbw80, FiveGhz).get_center_chan_idx().unwrap());
342 assert_eq!(58, Channel::new(64, Bandwidth::Cbw80, FiveGhz).get_center_chan_idx().unwrap());
343 assert_eq!(
344 106,
345 Channel::new(100, Bandwidth::Cbw80, FiveGhz).get_center_chan_idx().unwrap()
346 );
347 assert_eq!(
348 106,
349 Channel::new(112, Bandwidth::Cbw80, FiveGhz).get_center_chan_idx().unwrap()
350 );
351 assert_eq!(
352 122,
353 Channel::new(116, Bandwidth::Cbw80, FiveGhz).get_center_chan_idx().unwrap()
354 );
355 assert_eq!(
356 122,
357 Channel::new(128, Bandwidth::Cbw80, FiveGhz).get_center_chan_idx().unwrap()
358 );
359 assert_eq!(
360 138,
361 Channel::new(132, Bandwidth::Cbw80, FiveGhz).get_center_chan_idx().unwrap()
362 );
363 assert_eq!(
364 138,
365 Channel::new(144, Bandwidth::Cbw80, FiveGhz).get_center_chan_idx().unwrap()
366 );
367 assert_eq!(
368 155,
369 Channel::new(149, Bandwidth::Cbw80, FiveGhz).get_center_chan_idx().unwrap()
370 );
371 assert_eq!(
372 155,
373 Channel::new(161, Bandwidth::Cbw80, FiveGhz).get_center_chan_idx().unwrap()
374 );
375 assert_eq!(
376 171,
377 Channel::new(165, Bandwidth::Cbw80, FiveGhz).get_center_chan_idx().unwrap()
378 );
379 assert_eq!(
380 171,
381 Channel::new(177, Bandwidth::Cbw80, FiveGhz).get_center_chan_idx().unwrap()
382 );
383
384 assert_eq!(50, Channel::new(36, Bandwidth::Cbw160, FiveGhz).get_center_chan_idx().unwrap());
386 assert_eq!(50, Channel::new(64, Bandwidth::Cbw160, FiveGhz).get_center_chan_idx().unwrap());
387 assert_eq!(
388 114,
389 Channel::new(100, Bandwidth::Cbw160, FiveGhz).get_center_chan_idx().unwrap()
390 );
391 assert_eq!(
392 114,
393 Channel::new(128, Bandwidth::Cbw160, FiveGhz).get_center_chan_idx().unwrap()
394 );
395 assert_eq!(
396 163,
397 Channel::new(149, Bandwidth::Cbw160, FiveGhz).get_center_chan_idx().unwrap()
398 );
399 assert_eq!(
400 163,
401 Channel::new(177, Bandwidth::Cbw160, FiveGhz).get_center_chan_idx().unwrap()
402 );
403
404 assert_eq!(
406 42,
407 Channel::new(36, Bandwidth::Cbw80P80 { vht_secondary_80_channel: 155 }, FiveGhz)
408 .get_center_chan_idx()
409 .unwrap()
410 );
411
412 assert!(Channel::new(1, Bandwidth::Cbw40Below, TwoGhz).get_center_chan_idx().is_err());
417 assert!(Channel::new(255, Bandwidth::Cbw40, TwoGhz).get_center_chan_idx().is_err());
418 }
419
420 #[test]
421 fn test_get_center_freq() {
422 assert_eq!(
423 2412 as MHz,
424 Channel::new(1, Bandwidth::Cbw20, TwoGhz).get_center_freq().unwrap()
425 );
426 assert_eq!(
427 2437 as MHz,
428 Channel::new(6, Bandwidth::Cbw20, TwoGhz).get_center_freq().unwrap()
429 );
430 assert_eq!(
431 2447 as MHz,
432 Channel::new(6, Bandwidth::Cbw40, TwoGhz).get_center_freq().unwrap()
433 );
434 assert_eq!(
435 2427 as MHz,
436 Channel::new(6, Bandwidth::Cbw40Below, TwoGhz).get_center_freq().unwrap()
437 );
438 assert_eq!(
439 5180 as MHz,
440 Channel::new(36, Bandwidth::Cbw20, FiveGhz).get_center_freq().unwrap()
441 );
442 assert_eq!(
443 5190 as MHz,
444 Channel::new(36, Bandwidth::Cbw40, FiveGhz).get_center_freq().unwrap()
445 );
446 assert_eq!(
447 5210 as MHz,
448 Channel::new(36, Bandwidth::Cbw80, FiveGhz).get_center_freq().unwrap()
449 );
450 assert_eq!(
451 5775 as MHz,
452 Channel::new(149, Bandwidth::Cbw80, FiveGhz).get_center_freq().unwrap()
453 );
454 assert_eq!(
455 5855 as MHz,
456 Channel::new(165, Bandwidth::Cbw80, FiveGhz).get_center_freq().unwrap()
457 );
458 assert_eq!(
459 5250 as MHz,
460 Channel::new(36, Bandwidth::Cbw160, FiveGhz).get_center_freq().unwrap()
461 );
462 assert_eq!(
463 5570 as MHz,
464 Channel::new(100, Bandwidth::Cbw160, FiveGhz).get_center_freq().unwrap()
465 );
466 assert_eq!(
467 5815 as MHz,
468 Channel::new(149, Bandwidth::Cbw160, FiveGhz).get_center_freq().unwrap()
469 );
470 assert_eq!(
471 5815 as MHz,
472 Channel::new(165, Bandwidth::Cbw160, FiveGhz).get_center_freq().unwrap()
473 );
474 assert_eq!(
475 5815 as MHz,
476 Channel::new(173, Bandwidth::Cbw160, FiveGhz).get_center_freq().unwrap()
477 );
478 assert_eq!(
479 5210 as MHz,
480 Channel::new(36, Bandwidth::Cbw80P80 { vht_secondary_80_channel: 155 }, FiveGhz)
481 .get_center_freq()
482 .unwrap()
483 );
484 }
485
486 #[test]
487 fn test_primarychannel_from_freq() {
488 assert_eq!(Some(1), primary_channel_from_freq(2412));
489 assert_eq!(None, primary_channel_from_freq(2413));
491 assert_eq!(Some(6), primary_channel_from_freq(2437));
492 assert_eq!(Some(13), primary_channel_from_freq(2472));
493 assert_eq!(Some(14), primary_channel_from_freq(2484));
494 assert_eq!(None, primary_channel_from_freq(5160));
496 assert_eq!(Some(36), primary_channel_from_freq(5180));
497 assert_eq!(None, primary_channel_from_freq(5190));
499 assert_eq!(Some(165), primary_channel_from_freq(5825));
500 assert_eq!(Some(173), primary_channel_from_freq(5865));
501 assert_eq!(None, primary_channel_from_freq(2400));
503 assert_eq!(None, primary_channel_from_freq(5000));
505 assert_eq!(None, primary_channel_from_freq(5885));
507 }
508
509 const RX_PRIMARY_CHAN: u8 = 11;
510 const RX_PRIMARY_CHAN_5GHZ: u8 = 36;
511 const HT_PRIMARY_CHAN: u8 = 48;
512
513 #[test]
514 fn test_derive_channel_basic() {
515 let channel = derive_channel(
516 fidl_ieee80211::ChannelNumber { number: RX_PRIMARY_CHAN, band: TwoGhz },
517 None,
518 None,
519 None,
520 );
521 assert_eq!(channel, Channel::new(RX_PRIMARY_CHAN, Bandwidth::Cbw20, TwoGhz));
522 }
523
524 #[test]
525 fn test_derive_channel_with_dsss_param() {
526 let channel = derive_channel(
527 fidl_ieee80211::ChannelNumber { number: RX_PRIMARY_CHAN, band: TwoGhz },
528 Some(6),
529 None,
530 None,
531 );
532 assert_eq!(channel, Channel::new(6, Bandwidth::Cbw20, TwoGhz));
533 }
534
535 #[test]
536 fn test_derive_channel_with_ht_20mhz() {
537 let expected_channel = Channel::new(HT_PRIMARY_CHAN, Bandwidth::Cbw20, FiveGhz);
538
539 let test_params = [
540 (ie::StaChanWidth::TWENTY_MHZ, ie::SecChanOffset::SECONDARY_NONE),
541 (ie::StaChanWidth::TWENTY_MHZ, ie::SecChanOffset::SECONDARY_ABOVE),
542 (ie::StaChanWidth::TWENTY_MHZ, ie::SecChanOffset::SECONDARY_BELOW),
543 (ie::StaChanWidth::ANY, ie::SecChanOffset::SECONDARY_NONE),
544 ];
545
546 for (ht_width, sec_chan_offset) in test_params.iter() {
547 let ht_op = ht_op(HT_PRIMARY_CHAN, *ht_width, *sec_chan_offset);
548 let channel = derive_channel(
549 fidl_ieee80211::ChannelNumber { number: RX_PRIMARY_CHAN_5GHZ, band: FiveGhz },
550 Some(RX_PRIMARY_CHAN_5GHZ),
551 Some(ht_op),
552 None,
553 );
554 assert_eq!(channel, expected_channel);
555 }
556 }
557
558 #[test]
559 fn test_derive_channel_with_ht_40mhz() {
560 let ht_op =
561 ht_op(HT_PRIMARY_CHAN, ie::StaChanWidth::ANY, ie::SecChanOffset::SECONDARY_ABOVE);
562 let channel = derive_channel(
563 fidl_ieee80211::ChannelNumber { number: RX_PRIMARY_CHAN_5GHZ, band: FiveGhz },
564 Some(RX_PRIMARY_CHAN_5GHZ),
565 Some(ht_op),
566 None,
567 );
568 assert_eq!(channel, Channel::new(HT_PRIMARY_CHAN, Bandwidth::Cbw40, FiveGhz));
569 }
570
571 #[test]
572 fn test_derive_channel_with_ht_40mhz_below() {
573 let ht_op =
574 ht_op(HT_PRIMARY_CHAN, ie::StaChanWidth::ANY, ie::SecChanOffset::SECONDARY_BELOW);
575 let channel = derive_channel(
576 fidl_ieee80211::ChannelNumber { number: RX_PRIMARY_CHAN_5GHZ, band: FiveGhz },
577 Some(RX_PRIMARY_CHAN_5GHZ),
578 Some(ht_op),
579 None,
580 );
581 assert_eq!(channel, Channel::new(HT_PRIMARY_CHAN, Bandwidth::Cbw40Below, FiveGhz));
582 }
583
584 #[test]
585 fn test_derive_channel_with_vht_80mhz() {
586 let ht_op =
587 ht_op(HT_PRIMARY_CHAN, ie::StaChanWidth::ANY, ie::SecChanOffset::SECONDARY_ABOVE);
588 let vht_op = vht_op(ie::VhtChannelBandwidth::CBW_80_160_80P80, 8, 0);
589 let channel = derive_channel(
590 fidl_ieee80211::ChannelNumber { number: RX_PRIMARY_CHAN_5GHZ, band: FiveGhz },
591 Some(RX_PRIMARY_CHAN_5GHZ),
592 Some(ht_op),
593 Some(vht_op),
594 );
595 assert_eq!(channel, Channel::new(HT_PRIMARY_CHAN, Bandwidth::Cbw80, FiveGhz));
596 }
597
598 #[test]
599 fn test_derive_channel_with_vht_160mhz() {
600 let ht_op =
601 ht_op(HT_PRIMARY_CHAN, ie::StaChanWidth::ANY, ie::SecChanOffset::SECONDARY_ABOVE);
602 let vht_op = vht_op(ie::VhtChannelBandwidth::CBW_80_160_80P80, 0, 8);
603 let channel = derive_channel(
604 fidl_ieee80211::ChannelNumber { number: RX_PRIMARY_CHAN_5GHZ, band: FiveGhz },
605 Some(RX_PRIMARY_CHAN_5GHZ),
606 Some(ht_op),
607 Some(vht_op),
608 );
609 assert_eq!(channel, Channel::new(HT_PRIMARY_CHAN, Bandwidth::Cbw160, FiveGhz));
610 }
611
612 #[test]
613 fn test_derive_channel_with_vht_80plus80mhz() {
614 let ht_op =
615 ht_op(HT_PRIMARY_CHAN, ie::StaChanWidth::ANY, ie::SecChanOffset::SECONDARY_ABOVE);
616 let vht_op = vht_op(ie::VhtChannelBandwidth::CBW_80_160_80P80, 18, 1);
617 let channel = derive_channel(
618 fidl_ieee80211::ChannelNumber { number: RX_PRIMARY_CHAN_5GHZ, band: FiveGhz },
619 Some(RX_PRIMARY_CHAN_5GHZ),
620 Some(ht_op),
621 Some(vht_op),
622 );
623 assert_eq!(
624 channel,
625 Channel::new(
626 HT_PRIMARY_CHAN,
627 Bandwidth::Cbw80P80 { vht_secondary_80_channel: 1 },
628 FiveGhz
629 )
630 );
631 }
632
633 #[test]
634 fn test_derive_channel_none() {
635 let channel = derive_channel(rx_channel(8, TwoGhz), None, None, None);
636 assert_eq!(channel, Channel::new(8, Bandwidth::Cbw20, TwoGhz));
637 }
638
639 #[test]
640 fn test_derive_channel_no_rx_primary() {
641 let channel = derive_channel(rx_channel(8, TwoGhz), Some(6), None, None);
642 assert_eq!(channel, Channel::new(6, Bandwidth::Cbw20, TwoGhz))
643 }
644
645 fn ht_op(
646 primary_channel: u8,
647 chan_width: ie::StaChanWidth,
648 offset: ie::SecChanOffset,
649 ) -> ie::HtOperation {
650 let ht_op_info =
651 ie::HtOpInfo::new().with_sta_chan_width(chan_width).with_secondary_chan_offset(offset);
652 ie::HtOperation { primary_channel, ht_op_info, basic_ht_mcs_set: ie::SupportedMcsSet(0) }
653 }
654
655 fn vht_op(vht_cbw: ie::VhtChannelBandwidth, seg0: u8, seg1: u8) -> ie::VhtOperation {
656 ie::VhtOperation {
657 vht_cbw,
658 center_freq_seg0: seg0,
659 center_freq_seg1: seg1,
660 basic_mcs_nss: ie::VhtMcsNssMap(0),
661 }
662 }
663}