1use mac_parser::MACAddress;
2use scroll::{
3 ctx::{MeasureWith, TryFromCtx, TryIntoCtx},
4 Endian, Pread, Pwrite,
5};
6
7use crate::tlvs::{AWDLTLVType, AwdlTlv};
8
9use super::ChannelSequenceTLV;
10
11#[derive(Clone, Debug, Default, PartialEq, Eq)]
12pub struct SynchronizationParametersTLV {
14 pub next_channel: u8,
15 pub tx_counter: u16,
16 pub master_channel: u8,
17 pub guard_time: u8,
18 pub aw_period: u16,
19 pub af_period: u16,
20 pub awdl_flags: u16, pub aw_ext_length: u16,
22 pub aw_common_length: u16,
23 pub remaining_aw_length: u16,
24 pub min_ext_count: u8,
25 pub max_multicast_ext_count: u8,
26 pub max_unicast_ext_count: u8,
27 pub max_af_ext_count: u8,
28 pub master_address: MACAddress,
29 pub presence_mode: u8,
30 pub aw_seq_number: u16,
31 pub ap_beacon_alignment_delta: u16,
32 pub channel_sequence: ChannelSequenceTLV,
34}
35impl AwdlTlv for SynchronizationParametersTLV {
36 const TLV_TYPE: AWDLTLVType = AWDLTLVType::SynchronizationParameters;
37}
38impl MeasureWith<()> for SynchronizationParametersTLV {
39 fn measure_with(&self, ctx: &()) -> usize {
40 32 + self.channel_sequence.measure_with(ctx)
41 }
42}
43impl<'a> TryFromCtx<'a> for SynchronizationParametersTLV {
44 type Error = scroll::Error;
45 fn try_from_ctx(from: &'a [u8], _ctx: ()) -> Result<(Self, usize), Self::Error> {
46 let mut offset = 0;
47
48 let next_channel = from.gread_with(&mut offset, Endian::Little)?;
49 let tx_counter = from.gread_with(&mut offset, Endian::Little)?;
50 let master_channel = from.gread_with(&mut offset, Endian::Little)?;
51 let guard_time = from.gread_with(&mut offset, Endian::Little)?;
52 let aw_period = from.gread_with(&mut offset, Endian::Little)?;
53 let af_period = from.gread_with(&mut offset, Endian::Little)?;
54 let awdl_flags = from.gread_with(&mut offset, Endian::Little)?;
55 let aw_ext_length = from.gread_with(&mut offset, Endian::Little)?;
56 let aw_common_length = from.gread_with(&mut offset, Endian::Little)?;
57 let remaining_aw_length = from.gread_with(&mut offset, Endian::Little)?;
58 let min_ext_count = from.gread_with(&mut offset, Endian::Little)?;
59 let max_multicast_ext_count = from.gread_with(&mut offset, Endian::Little)?;
60 let max_unicast_ext_count = from.gread_with(&mut offset, Endian::Little)?;
61 let max_af_ext_count = from.gread_with(&mut offset, Endian::Little)?;
62 let master_address = from.gread(&mut offset)?;
63 let presence_mode = from.gread_with(&mut offset, Endian::Little)?;
64 offset += 1;
65 let aw_seq_number = from.gread_with(&mut offset, Endian::Little)?;
66 let ap_beacon_alignment_delta = from.gread_with(&mut offset, Endian::Little)?;
67 let channel_sequence = from.gread(&mut offset)?;
68 Ok((
69 Self {
70 next_channel,
71 tx_counter,
72 master_channel,
73 guard_time,
74 aw_period,
75 af_period,
76 awdl_flags,
77 aw_ext_length,
78 aw_common_length,
79 remaining_aw_length,
80 min_ext_count,
81 max_multicast_ext_count,
82 max_unicast_ext_count,
83 max_af_ext_count,
84 master_address,
85 presence_mode,
86 aw_seq_number,
87 ap_beacon_alignment_delta,
88 channel_sequence,
89 },
90 offset,
91 ))
92 }
93}
94impl TryIntoCtx for SynchronizationParametersTLV {
95 type Error = scroll::Error;
96 fn try_into_ctx(self, buf: &mut [u8], _ctx: ()) -> Result<usize, Self::Error> {
97 let mut offset = 0;
98
99 buf.gwrite_with(self.next_channel, &mut offset, Endian::Little)?;
100 buf.gwrite_with(self.tx_counter, &mut offset, Endian::Little)?;
101 buf.gwrite_with(self.master_channel, &mut offset, Endian::Little)?;
102 buf.gwrite_with(self.guard_time, &mut offset, Endian::Little)?;
103 buf.gwrite_with(self.aw_period, &mut offset, Endian::Little)?;
104 buf.gwrite_with(self.af_period, &mut offset, Endian::Little)?;
105 buf.gwrite_with(self.awdl_flags, &mut offset, Endian::Little)?;
106 buf.gwrite_with(self.aw_ext_length, &mut offset, Endian::Little)?;
107 buf.gwrite_with(self.aw_common_length, &mut offset, Endian::Little)?;
108 buf.gwrite_with(self.remaining_aw_length, &mut offset, Endian::Little)?;
109 buf.gwrite_with(self.min_ext_count, &mut offset, Endian::Little)?;
110 buf.gwrite_with(self.max_multicast_ext_count, &mut offset, Endian::Little)?;
111 buf.gwrite_with(self.max_unicast_ext_count, &mut offset, Endian::Little)?;
112 buf.gwrite_with(self.max_af_ext_count, &mut offset, Endian::Little)?;
113 buf.gwrite(self.master_address, &mut offset)?;
114 buf.gwrite_with(self.presence_mode, &mut offset, Endian::Little)?;
115 offset += 1;
116 buf.gwrite_with(self.aw_seq_number, &mut offset, Endian::Little)?;
117 buf.gwrite_with(self.ap_beacon_alignment_delta, &mut offset, Endian::Little)?;
118 buf.gwrite(self.channel_sequence, &mut offset)?;
119
120 offset -= 1;
121
122 Ok(offset)
123 }
124}
125#[cfg(test)]
126#[test]
127fn test_sync_parameters_tlv() {
128 use core::num::NonZeroU8;
129
130 use alloc::vec;
131
132 use crate::tlvs::sync_elect::{
133 channel::{Band, ChannelBandwidth, LegacyFlags, SupportChannel},
134 channel_sequence::ChannelSequence,
135 };
136
137 let bytes = &include_bytes!("../../../test_bins/sync_parameters_tlv.bin")[3..];
138
139 let sync_parameters_tlv = bytes.pread::<SynchronizationParametersTLV>(0).unwrap();
140 assert_eq!(
141 sync_parameters_tlv,
142 SynchronizationParametersTLV {
143 next_channel: 44,
144 tx_counter: 49,
145 master_channel: 6,
146 guard_time: 0,
147 aw_period: 16,
148 af_period: 110,
149 awdl_flags: 0x1800,
150 aw_ext_length: 16,
151 aw_common_length: 16,
152 remaining_aw_length: 1,
153 min_ext_count: 3,
154 max_multicast_ext_count: 3,
155 max_unicast_ext_count: 3,
156 max_af_ext_count: 3,
157 master_address: [0xce, 0x21, 0x1f, 0x62, 0x21, 0x22].into(),
158 presence_mode: 4,
159 aw_seq_number: 1988,
160 ap_beacon_alignment_delta: 1986,
161 channel_sequence: ChannelSequenceTLV {
162 step_count: NonZeroU8::new(4).unwrap(),
163 channel_sequence: ChannelSequence::Legacy([
164 (
165 LegacyFlags {
166 support_channel: SupportChannel::Lower,
167 channel_bandwidth: ChannelBandwidth::EightyMHz,
168 band: Band::FiveGHz
169 },
170 46
171 ),
172 (
173 LegacyFlags {
174 support_channel: SupportChannel::Lower,
175 channel_bandwidth: ChannelBandwidth::EightyMHz,
176 band: Band::FiveGHz
177 },
178 46
179 ),
180 (
181 LegacyFlags {
182 support_channel: SupportChannel::Lower,
183 channel_bandwidth: ChannelBandwidth::EightyMHz,
184 band: Band::FiveGHz
185 },
186 46
187 ),
188 (
189 LegacyFlags {
190 support_channel: SupportChannel::Lower,
191 channel_bandwidth: ChannelBandwidth::EightyMHz,
192 band: Band::FiveGHz
193 },
194 46
195 ),
196 (
197 LegacyFlags {
198 support_channel: SupportChannel::Primary,
199 channel_bandwidth: ChannelBandwidth::FourtyMHz,
200 band: Band::TwoPointFourGHz
201 },
202 8
203 ),
204 (
205 LegacyFlags {
206 support_channel: SupportChannel::Primary,
207 channel_bandwidth: ChannelBandwidth::FourtyMHz,
208 band: Band::TwoPointFourGHz
209 },
210 8
211 ),
212 (
213 LegacyFlags {
214 support_channel: SupportChannel::Primary,
215 channel_bandwidth: ChannelBandwidth::FourtyMHz,
216 band: Band::TwoPointFourGHz
217 },
218 8
219 ),
220 (
221 LegacyFlags {
222 support_channel: SupportChannel::Primary,
223 channel_bandwidth: ChannelBandwidth::FourtyMHz,
224 band: Band::TwoPointFourGHz
225 },
226 8
227 ),
228 (
229 LegacyFlags {
230 support_channel: SupportChannel::Lower,
231 channel_bandwidth: ChannelBandwidth::EightyMHz,
232 band: Band::FiveGHz
233 },
234 46
235 ),
236 (
237 LegacyFlags {
238 support_channel: SupportChannel::Lower,
239 channel_bandwidth: ChannelBandwidth::EightyMHz,
240 band: Band::FiveGHz
241 },
242 46
243 ),
244 (
245 LegacyFlags {
246 support_channel: SupportChannel::Lower,
247 channel_bandwidth: ChannelBandwidth::EightyMHz,
248 band: Band::FiveGHz
249 },
250 46
251 ),
252 (
253 LegacyFlags {
254 support_channel: SupportChannel::Lower,
255 channel_bandwidth: ChannelBandwidth::EightyMHz,
256 band: Band::FiveGHz
257 },
258 46
259 ),
260 (
261 LegacyFlags {
262 support_channel: SupportChannel::Lower,
263 channel_bandwidth: ChannelBandwidth::EightyMHz,
264 band: Band::FiveGHz
265 },
266 38
267 ),
268 (
269 LegacyFlags {
270 support_channel: SupportChannel::Lower,
271 channel_bandwidth: ChannelBandwidth::EightyMHz,
272 band: Band::FiveGHz
273 },
274 38
275 ),
276 (
277 LegacyFlags {
278 support_channel: SupportChannel::Lower,
279 channel_bandwidth: ChannelBandwidth::EightyMHz,
280 band: Band::FiveGHz
281 },
282 38
283 ),
284 (
285 LegacyFlags {
286 support_channel: SupportChannel::Lower,
287 channel_bandwidth: ChannelBandwidth::EightyMHz,
288 band: Band::FiveGHz
289 },
290 38
291 ),
292 ])
293 }
294 }
295 );
296 let mut buf = vec![0x00; sync_parameters_tlv.measure_with(&())];
297 buf.as_mut_slice().pwrite(sync_parameters_tlv, 0).unwrap();
298 assert_eq!(buf, bytes);
299}