1use core::fmt::Debug;
4
5use bitfield_struct::bitfield;
6use macro_bits::serializable_enum;
7use scroll::{
8 ctx::{MeasureWith, TryFromCtx, TryIntoCtx},
9 Endian, Pread, Pwrite,
10};
11
12use super::{Element, ElementID};
13
14#[bitfield(u32, defmt = cfg(feature = "defmt"))]
15#[derive(PartialEq, Eq, Hash)]
16pub struct VHTCapabilitiesInfo {
18 #[bits(2)]
19 pub maximum_mpdu_length: u8,
20 #[bits(2)]
21 pub supported_channel_width_set: u8,
22 pub rx_ldpc: bool,
23 pub short_gi_80mhz: bool,
24 pub short_gi_160mhz: bool,
25 pub tx_stbc: bool,
26 #[bits(3)]
27 pub rx_stbc: u8,
28 pub su_beamformer_capable: bool,
29 pub su_beamformee_capable: bool,
30 #[bits(3)]
31 pub beamformee_sts_capability: u8,
32 #[bits(3)]
33 pub number_of_sounding_dimensions: u8,
34 pub mu_beamformer_capable: bool,
35 pub mu_beamformee_capable: bool,
36 pub txop_ps: bool,
37 pub htc_vht_capable: bool,
38 #[bits(3)]
39 pub maximum_ampdu_length_exponent: u8,
40 #[bits(2)]
41 pub vht_link_adaptation_capable: u8,
42 pub rx_antenna_pattern_consistency: bool,
43 pub tx_antenna_pattern_consistency: bool,
44 #[bits(2)]
45 pub extended_nss_bw_support: u8,
46}
47impl VHTCapabilitiesInfo {
48 pub const fn maximum_mpdu_length_in_bytes(&self) -> Option<u16> {
49 match self.maximum_mpdu_length() {
50 0 => Some(3_895),
51 1 => Some(7_991),
52 2 => Some(11_454),
53 _ => None,
54 }
55 }
56 pub const fn with_maximum_mpdu_length_in_bytes(
57 self,
58 maximum_mpdu_length_in_bytes: u16,
59 ) -> Self {
60 self.with_maximum_mpdu_length(match maximum_mpdu_length_in_bytes {
61 3_895 => 0,
62 7_991 => 1,
63 11_454 => 2,
64 _ => 3,
65 })
66 }
67 pub fn set_maximum_mpdu_length_in_bytes(&mut self, maximum_mpdu_length_in_bytes: u16) {
68 *self = self.with_maximum_mpdu_length_in_bytes(maximum_mpdu_length_in_bytes);
69 }
70}
71serializable_enum! {
72 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
73 pub enum VHTMCSSupport : u8 {
75 ZeroToSeven => 0,
76 ZeroToEight => 1,
77 ZeroToNine => 2,
78 #[default]
79 NotSupported => 3
80 }
81}
82#[derive(Clone, Copy, Default, PartialEq, Eq, Hash)]
83pub struct VHTMCSMap(u16);
85impl VHTMCSMap {
86 pub const fn from_bits(bits: u16) -> Self {
87 Self(bits)
88 }
89 pub const fn into_bits(self) -> u16 {
90 self.0
91 }
92 pub fn vht_mcs_support_for_nss(&self, nss: usize) -> Option<VHTMCSSupport> {
94 if (1..9).contains(&nss) {
95 Some(VHTMCSSupport::from_bits(
96 ((self.0 >> ((nss - 1) * 2)) & 0b0000_0011) as u8,
97 ))
98 } else {
99 None
100 }
101 }
102 pub fn vht_mcs_support_iter(&self) -> impl Iterator<Item = VHTMCSSupport> + '_ {
104 (1..9).filter_map(|nss| self.vht_mcs_support_for_nss(nss))
105 }
106 pub fn from_vht_mcs_iter(iter: impl IntoIterator<Item = VHTMCSSupport>) -> Self {
108 Self(
109 iter.into_iter()
110 .take(8)
111 .enumerate()
112 .fold(0u16, |acc, (i, vht_mcs_support)| {
113 acc | (vht_mcs_support.into_bits() << (i * 2)) as u16
114 }),
115 )
116 }
117}
118impl Debug for VHTMCSMap {
119 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
120 f.debug_list().entries(self.vht_mcs_support_iter()).finish()
121 }
122}
123#[bitfield(u64)]
124#[derive(PartialEq, Eq, Hash)]
125pub struct SupportedVHTMCSAndNSSSet {
126 #[bits(16)]
127 pub rx_vht_mcs_map: VHTMCSMap,
128 #[bits(13)]
129 pub rx_highest_supported_long_gi_data_rate: u16,
130 #[bits(3)]
131 pub maximum_nsts_total: u8,
132 #[bits(16)]
133 pub tx_vht_mcs_map: VHTMCSMap,
134 #[bits(13)]
135 pub tx_highest_supported_long_gi_data_rate: u16,
136 pub vht_extended_nss_bw_capable: bool,
137 #[bits(2)]
138 pub __: u8,
139}
140
141#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
142pub struct VHTCapabilitiesElement {
144 pub vht_capabilities_info: VHTCapabilitiesInfo,
145 pub supported_vht_mcs_and_nss_set: SupportedVHTMCSAndNSSSet,
146}
147impl TryFromCtx<'_> for VHTCapabilitiesElement {
148 type Error = scroll::Error;
149 fn try_from_ctx(from: &'_ [u8], _ctx: ()) -> Result<(Self, usize), Self::Error> {
150 let mut offset = 0;
151 let vht_capabilities_info =
152 VHTCapabilitiesInfo::from_bits(from.gread_with(&mut offset, Endian::Little)?);
153 let supported_vht_mcs_and_nss_set =
154 SupportedVHTMCSAndNSSSet::from_bits(from.gread_with(&mut offset, Endian::Little)?);
155 Ok((
156 Self {
157 vht_capabilities_info,
158 supported_vht_mcs_and_nss_set,
159 },
160 offset,
161 ))
162 }
163}
164impl MeasureWith<()> for VHTCapabilitiesElement {
165 fn measure_with(&self, _ctx: &()) -> usize {
166 12
167 }
168}
169impl TryIntoCtx for VHTCapabilitiesElement {
170 type Error = scroll::Error;
171 fn try_into_ctx(self, buf: &mut [u8], _ctx: ()) -> Result<usize, Self::Error> {
172 let mut offset = 0;
173 buf.gwrite_with(
174 self.vht_capabilities_info.into_bits(),
175 &mut offset,
176 Endian::Little,
177 )?;
178 buf.gwrite_with(
179 self.supported_vht_mcs_and_nss_set.into_bits(),
180 &mut offset,
181 Endian::Little,
182 )?;
183 Ok(offset)
184 }
185}
186impl Element for VHTCapabilitiesElement {
187 const ELEMENT_ID: ElementID = ElementID::Id(0xbf);
188 type ReadType<'a> = VHTCapabilitiesElement;
189}
190serializable_enum! {
191 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
192 pub enum ChannelWidth : u8 {
193 TwentyOrFourtyMHz => 0,
194 EightyOneSixtyOrEightyPlusEightyMhz => 1,
195 OneSixtyMHz => 2,
196 NonContiguousEightyPlusEightyMHz => 3
197 }
198}
199#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
200pub struct VHTOperationElement {
202 pub channel_bandwidth: ChannelWidth,
203 pub channel_center_frequency_segment_0: u8,
204 pub channel_center_frequency_segment_1: u8,
205 pub basic_vht_mcs_and_nss_set: VHTMCSMap,
206}
207impl TryFromCtx<'_> for VHTOperationElement {
208 type Error = scroll::Error;
209 fn try_from_ctx(from: &'_ [u8], _ctx: ()) -> Result<(Self, usize), Self::Error> {
210 let mut offset = 0;
211
212 let channel_bandwidth = ChannelWidth::from_bits(from.gread(&mut offset)?);
213 let channel_center_frequency_segment_0 = from.gread(&mut offset)?;
214 let channel_center_frequency_segment_1 = from.gread(&mut offset)?;
215 let basic_vht_mcs_and_nss_set =
216 VHTMCSMap::from_bits(from.gread_with(&mut offset, Endian::Little)?);
217
218 Ok((
219 Self {
220 channel_bandwidth,
221 channel_center_frequency_segment_0,
222 channel_center_frequency_segment_1,
223 basic_vht_mcs_and_nss_set,
224 },
225 offset,
226 ))
227 }
228}
229impl MeasureWith<()> for VHTOperationElement {
230 fn measure_with(&self, _ctx: &()) -> usize {
231 5
232 }
233}
234impl TryIntoCtx for VHTOperationElement {
235 type Error = scroll::Error;
236 fn try_into_ctx(self, buf: &mut [u8], _ctx: ()) -> Result<usize, Self::Error> {
237 let mut offset = 0;
238
239 buf.gwrite(self.channel_bandwidth.into_bits(), &mut offset)?;
240 buf.gwrite(self.channel_center_frequency_segment_0, &mut offset)?;
241 buf.gwrite(self.channel_center_frequency_segment_1, &mut offset)?;
242 buf.gwrite_with(
243 self.basic_vht_mcs_and_nss_set.into_bits(),
244 &mut offset,
245 Endian::Little,
246 )?;
247
248 Ok(offset)
249 }
250}
251impl Element for VHTOperationElement {
252 const ELEMENT_ID: ElementID = ElementID::Id(0xc0);
253 type ReadType<'a> = VHTOperationElement;
254}