awdl_frame_parser/tlvs/sync_elect/
synchronization_parameters_tlv.rs

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)]
12/// The synchronization parameters of the peer.
13pub 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, // Don't ask, don't know either.
21    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    /// This isn't actually a TLV, but contains the functionality we need.
33    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}