wlan_common/mac/ctrl/
mod.rs

1// Copyright 2019 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use super::{CtrlFrame, CtrlSubtype};
6use zerocopy::{Ref, SplitByteSlice};
7
8mod fields;
9
10pub use fields::*;
11
12#[derive(Debug)]
13pub enum CtrlBody<B: SplitByteSlice> {
14    PsPoll { ps_poll: Ref<B, PsPoll> },
15    Unsupported { subtype: CtrlSubtype },
16}
17
18impl<B: SplitByteSlice> CtrlBody<B> {
19    pub fn parse(subtype: CtrlSubtype, bytes: B) -> Option<Self> {
20        match subtype {
21            CtrlSubtype::PS_POLL => {
22                let (ps_poll, _) = Ref::from_prefix(bytes).ok()?;
23                Some(CtrlBody::PsPoll { ps_poll })
24            }
25            subtype => Some(CtrlBody::Unsupported { subtype }),
26        }
27    }
28}
29
30impl<B> TryFrom<CtrlFrame<B>> for CtrlBody<B>
31where
32    B: SplitByteSlice,
33{
34    type Error = ();
35
36    fn try_from(ctrl_frame: CtrlFrame<B>) -> Result<Self, Self::Error> {
37        CtrlBody::parse(ctrl_frame.ctrl_subtype(), ctrl_frame.body).ok_or(())
38    }
39}
40
41#[cfg(test)]
42mod tests {
43    use super::*;
44    use crate::assert_variant;
45    use ieee80211::{Bssid, MacAddr};
46
47    #[test]
48    fn parse_ps_poll_frame() {
49        let bytes = vec![
50            0b00000001, 0b11000000, // Masked AID
51            2, 2, 2, 2, 2, 2, // addr1
52            4, 4, 4, 4, 4, 4, // addr2
53        ];
54        assert_variant!(
55            CtrlBody::parse(CtrlSubtype::PS_POLL, &bytes[..]),
56            Some(CtrlBody::PsPoll { ps_poll }) => {
57                assert_eq!(0b1100000000000001, { ps_poll.masked_aid });
58                assert_eq!(Bssid::from([2; 6]), ps_poll.bssid);
59                assert_eq!(MacAddr::from([4; 6]), ps_poll.ta);
60            },
61            "expected PS-Poll frame"
62        );
63    }
64}