• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #![allow(clippy::all)]
16 #![allow(non_upper_case_globals)]
17 #![allow(non_camel_case_types)]
18 #![allow(non_snake_case)]
19 #![allow(unused)]
20 #![allow(missing_docs)]
21 
22 use std::cmp;
23 
24 use log::error;
25 use num_derive::FromPrimitive;
26 use num_traits::FromPrimitive;
27 use zeroize::Zeroize;
28 
29 include!(concat!(env!("OUT_DIR"), "/uci_packets.rs"));
30 
31 const MAX_PAYLOAD_LEN: usize = 255;
32 // TODO: Use a PDL struct to represent the headers and avoid hardcoding
33 // lengths below.
34 // Real UCI packet header len.
35 pub const UCI_PACKET_HAL_HEADER_LEN: usize = 4;
36 // Unfragmented UCI packet header len.
37 pub const UCI_PACKET_HEADER_LEN: usize = 7;
38 // Unfragmented UCI DATA_MESSAGE_SND packet header len.
39 const UCI_DATA_SND_PACKET_HEADER_LEN: usize = 6;
40 
41 // Opcode field byte position (within UCI packet header) and mask (of bits to be used).
42 const UCI_HEADER_MT_BYTE_POSITION: usize = 0;
43 const UCI_HEADER_MT_BIT_SHIFT: u8 = 5;
44 const UCI_HEADER_MT_MASK: u8 = 0x7;
45 
46 const UCI_HEADER_PBF_BYTE_POSITION: usize = 0;
47 const UCI_HEADER_PBF_BIT_SHIFT: u8 = 4;
48 const UCI_HEADER_PBF_MASK: u8 = 0x1;
49 
50 const UCI_CONTROL_HEADER_GID_BYTE_POSITION: usize = 0;
51 const UCI_CONTROL_HEADER_GID_MASK: u8 = 0xF;
52 
53 const UCI_CONTROL_HEADER_OID_BYTE_POSITION: usize = 1;
54 const UCI_CONTROL_HEADER_OID_MASK: u8 = 0x3F;
55 
56 #[derive(Debug, Clone, PartialEq, FromPrimitive)]
57 pub enum TimeStampLength {
58     Timestamp40Bit = 0x0,
59     Timestamp64Bit = 0x1,
60 }
61 
62 #[derive(Debug, Clone, PartialEq, FromPrimitive)]
63 pub enum DTAnchorLocationType {
64     NotIncluded = 0x0,
65     Wgs84 = 0x1,
66     Relative = 0x2,
67 }
68 
69 #[allow(dead_code)]
70 #[derive(Debug, Clone, PartialEq)]
71 pub struct DlTdoaRangingMeasurement {
72     pub status: u8,
73     pub message_type: u8,
74     pub message_control: u16,
75     pub block_index: u16,
76     pub round_index: u8,
77     pub nlos: u8,
78     pub aoa_azimuth: u16,
79     pub aoa_azimuth_fom: u8,
80     pub aoa_elevation: u16,
81     pub aoa_elevation_fom: u8,
82     pub rssi: u8,
83     pub tx_timestamp: u64,
84     pub rx_timestamp: u64,
85     pub anchor_cfo: u16,
86     pub cfo: u16,
87     pub initiator_reply_time: u32,
88     pub responder_reply_time: u32,
89     pub initiator_responder_tof: u16,
90     pub dt_anchor_location: Vec<u8>,
91     pub ranging_rounds: Vec<u8>,
92     total_size: usize,
93 }
94 
95 impl DlTdoaRangingMeasurement {
parse_one(bytes: &[u8]) -> Option<Self>96     pub fn parse_one(bytes: &[u8]) -> Option<Self> {
97         let mut ptr = 0;
98         let status = extract_u8(bytes, &mut ptr, 1)?;
99         let message_type = extract_u8(bytes, &mut ptr, 1)?;
100         let message_control = extract_u16(bytes, &mut ptr, 2)?;
101         let block_index = extract_u16(bytes, &mut ptr, 2)?;
102         let round_index = extract_u8(bytes, &mut ptr, 1)?;
103         let nlos = extract_u8(bytes, &mut ptr, 1)?;
104         let aoa_azimuth = extract_u16(bytes, &mut ptr, 2)?;
105         let aoa_azimuth_fom = extract_u8(bytes, &mut ptr, 1)?;
106         let aoa_elevation = extract_u16(bytes, &mut ptr, 2)?;
107         let aoa_elevation_fom = extract_u8(bytes, &mut ptr, 1)?;
108         let rssi = extract_u8(bytes, &mut ptr, 1)?;
109         let tx_timestamp_length = (message_control >> 1) & 0x1;
110         let tx_timestamp = match TimeStampLength::from_u16(tx_timestamp_length)? {
111             TimeStampLength::Timestamp40Bit => extract_u64(bytes, &mut ptr, 5)?,
112             TimeStampLength::Timestamp64Bit => extract_u64(bytes, &mut ptr, 8)?,
113         };
114         let rx_timestamp_length = (message_control >> 3) & 0x1;
115         let rx_timestamp = match TimeStampLength::from_u16(rx_timestamp_length)? {
116             TimeStampLength::Timestamp40Bit => extract_u64(bytes, &mut ptr, 5)?,
117             TimeStampLength::Timestamp64Bit => extract_u64(bytes, &mut ptr, 8)?,
118         };
119         let anchor_cfo = extract_u16(bytes, &mut ptr, 2)?;
120         let cfo = extract_u16(bytes, &mut ptr, 2)?;
121         let initiator_reply_time = extract_u32(bytes, &mut ptr, 4)?;
122         let responder_reply_time = extract_u32(bytes, &mut ptr, 4)?;
123         let initiator_responder_tof = extract_u16(bytes, &mut ptr, 2)?;
124         let dt_location_type = (message_control >> 5) & 0x3;
125         let dt_anchor_location = match DTAnchorLocationType::from_u16(dt_location_type)? {
126             DTAnchorLocationType::Wgs84 => extract_vec(bytes, &mut ptr, 10)?,
127             DTAnchorLocationType::Relative => extract_vec(bytes, &mut ptr, 12)?,
128             _ => vec![],
129         };
130         let active_ranging_rounds = ((message_control >> 7) & 0xf) as u8;
131         let ranging_round = extract_vec(bytes, &mut ptr, active_ranging_rounds as usize)?;
132 
133         Some(DlTdoaRangingMeasurement {
134             status,
135             message_type,
136             message_control,
137             block_index,
138             round_index,
139             nlos,
140             aoa_azimuth,
141             aoa_azimuth_fom,
142             aoa_elevation,
143             aoa_elevation_fom,
144             rssi,
145             tx_timestamp,
146             rx_timestamp,
147             anchor_cfo,
148             cfo,
149             initiator_reply_time,
150             responder_reply_time,
151             initiator_responder_tof,
152             dt_anchor_location: dt_anchor_location.to_vec(),
153             ranging_rounds: ranging_round.to_vec(),
154             total_size: ptr,
155         })
156     }
get_total_size(&self) -> usize157     pub fn get_total_size(&self) -> usize {
158         self.total_size
159     }
160 }
161 
162 #[derive(Debug, Clone, PartialEq)]
163 pub struct ShortAddressDlTdoaRangingMeasurement {
164     pub mac_address: u16,
165     pub measurement: DlTdoaRangingMeasurement,
166 }
167 
168 impl ShortAddressDlTdoaRangingMeasurement {
169     /// Parse the `payload` byte buffer from PDL to the vector of measurement.
parse(bytes: &[u8], no_of_ranging_measurement: u8) -> Option<Vec<Self>>170     pub fn parse(bytes: &[u8], no_of_ranging_measurement: u8) -> Option<Vec<Self>> {
171         let mut ptr = 0;
172         let mut measurements = vec![];
173         let mut count = 0;
174         while (count < no_of_ranging_measurement) {
175             let mac_address = extract_u16(bytes, &mut ptr, 2)?;
176             let rem = &bytes[ptr..];
177             let measurement = DlTdoaRangingMeasurement::parse_one(rem);
178             match measurement {
179                 Some(measurement) => {
180                     ptr += measurement.get_total_size();
181                     measurements
182                         .push(ShortAddressDlTdoaRangingMeasurement { mac_address, measurement });
183                     count = count + 1;
184                 }
185                 None => return None,
186             }
187         }
188         Some(measurements)
189     }
190 }
191 
192 #[derive(Debug, Clone, PartialEq)]
193 pub struct ExtendedAddressDlTdoaRangingMeasurement {
194     pub mac_address: u64,
195     pub measurement: DlTdoaRangingMeasurement,
196 }
197 
198 impl ExtendedAddressDlTdoaRangingMeasurement {
199     /// Parse the `payload` byte buffer from PDL to the vector of measurement.
parse(bytes: &[u8], no_of_ranging_measurement: u8) -> Option<Vec<Self>>200     pub fn parse(bytes: &[u8], no_of_ranging_measurement: u8) -> Option<Vec<Self>> {
201         let mut ptr = 0;
202         let mut measurements = vec![];
203         let mut count = 0;
204         while (count < no_of_ranging_measurement) {
205             let mac_address = extract_u64(bytes, &mut ptr, 8)?;
206             let rem = &bytes[ptr..];
207             let measurement = DlTdoaRangingMeasurement::parse_one(rem);
208             match measurement {
209                 Some(measurement) => {
210                     ptr += measurement.get_total_size();
211                     measurements
212                         .push(ExtendedAddressDlTdoaRangingMeasurement { mac_address, measurement });
213                     count = count + 1;
214                 }
215                 None => return None,
216             }
217         }
218         Some(measurements)
219     }
220 }
221 
extract_vec(bytes: &[u8], ptr: &mut usize, consumed_size: usize) -> Option<Vec<u8>>222 pub fn extract_vec(bytes: &[u8], ptr: &mut usize, consumed_size: usize) -> Option<Vec<u8>> {
223     if bytes.len() < *ptr + consumed_size {
224         return None;
225     }
226 
227     let res = bytes[*ptr..*ptr + consumed_size].to_vec();
228     *ptr += consumed_size;
229     Some(res)
230 }
231 
232 /// Generate the function that extracts the value from byte buffers.
233 macro_rules! generate_extract_func {
234     ($func_name:ident, $type:ty) => {
235         /// Extract the value from |byte[ptr..ptr + consumed_size]| in little endian.
236         fn $func_name(bytes: &[u8], ptr: &mut usize, consumed_size: usize) -> Option<$type> {
237             const type_size: usize = std::mem::size_of::<$type>();
238             if consumed_size > type_size {
239                 return None;
240             }
241 
242             let extracted_bytes = extract_vec(bytes, ptr, consumed_size)?;
243             let mut le_bytes = [0; type_size];
244             le_bytes[0..consumed_size].copy_from_slice(&extracted_bytes);
245             Some(<$type>::from_le_bytes(le_bytes))
246         }
247     };
248 }
249 
250 generate_extract_func!(extract_u8, u8);
251 generate_extract_func!(extract_u16, u16);
252 generate_extract_func!(extract_u32, u32);
253 generate_extract_func!(extract_u64, u64);
254 
255 // The GroupIdOrDataPacketFormat enum has all the values defined in both the GroupId and
256 // DataPacketFormat enums. It represents the same bits in UCI packet header - the GID field in
257 // a UCI control packet, and the DataPacketFormat field in a UCI data packet. Hence the unwrap()
258 // calls in the conversions below should always succeed (as long as care is taken in future, to
259 // keep the two enums in sync, for any additional values defined in the UCI spec).
260 impl From<GroupId> for GroupIdOrDataPacketFormat {
from(gid: GroupId) -> Self261     fn from(gid: GroupId) -> Self {
262         GroupIdOrDataPacketFormat::try_from(u8::from(gid)).unwrap()
263     }
264 }
265 
266 impl From<GroupIdOrDataPacketFormat> for GroupId {
from(gid_or_dpf: GroupIdOrDataPacketFormat) -> Self267     fn from(gid_or_dpf: GroupIdOrDataPacketFormat) -> Self {
268         GroupId::try_from(u8::from(gid_or_dpf)).unwrap()
269     }
270 }
271 
272 impl From<DataPacketFormat> for GroupIdOrDataPacketFormat {
from(dpf: DataPacketFormat) -> Self273     fn from(dpf: DataPacketFormat) -> Self {
274         GroupIdOrDataPacketFormat::try_from(u8::from(dpf)).unwrap()
275     }
276 }
277 
278 // The GroupIdOrDataPacketFormat enum has more values defined (for the GroupId bits) than the
279 // DataPacketFormat enum. Hence this is implemented as TryFrom() instead of From().
280 impl TryFrom<GroupIdOrDataPacketFormat> for DataPacketFormat {
281     type Error = Error;
282 
try_from(gid_or_dpf: GroupIdOrDataPacketFormat) -> Result<Self>283     fn try_from(gid_or_dpf: GroupIdOrDataPacketFormat) -> Result<Self> {
284         DataPacketFormat::try_from(u8::from(gid_or_dpf)).or(Err(Error::InvalidPacketError))
285     }
286 }
287 
288 // Container for UCI packet header fields.
289 struct UciControlPacketHeader {
290     message_type: MessageType,
291     group_id: GroupId,
292     opcode: u8,
293 }
294 
295 impl UciControlPacketHeader {
new(message_type: MessageType, group_id: GroupId, opcode: u8) -> Result<Self>296     fn new(message_type: MessageType, group_id: GroupId, opcode: u8) -> Result<Self> {
297         if !is_uci_control_packet(message_type) {
298             return Err(Error::InvalidPacketError);
299         }
300 
301         Ok(UciControlPacketHeader {
302             message_type: message_type,
303             group_id: group_id,
304             opcode: opcode,
305         })
306     }
307 }
308 
309 // Helper methods to extract the UCI Packet header fields.
get_mt_from_uci_packet(packet: &[u8]) -> u8310 fn get_mt_from_uci_packet(packet: &[u8]) -> u8 {
311     (packet[UCI_HEADER_MT_BYTE_POSITION] >> UCI_HEADER_MT_BIT_SHIFT) & UCI_HEADER_MT_MASK
312 }
313 
get_pbf_from_uci_packet(packet: &[u8]) -> u8314 fn get_pbf_from_uci_packet(packet: &[u8]) -> u8 {
315     (packet[UCI_HEADER_PBF_BYTE_POSITION] >> UCI_HEADER_PBF_BIT_SHIFT) & UCI_HEADER_PBF_MASK
316 }
317 
get_gid_from_uci_control_packet(packet: &[u8]) -> u8318 fn get_gid_from_uci_control_packet(packet: &[u8]) -> u8 {
319     packet[UCI_CONTROL_HEADER_GID_BYTE_POSITION] & UCI_CONTROL_HEADER_GID_MASK
320 }
321 
get_oid_from_uci_control_packet(packet: &[u8]) -> u8322 fn get_oid_from_uci_control_packet(packet: &[u8]) -> u8 {
323     packet[UCI_CONTROL_HEADER_OID_BYTE_POSITION] & UCI_CONTROL_HEADER_OID_MASK
324 }
325 
326 // This function parses the packet bytes to return the Control Packet Opcode (OID) field. The
327 // caller should check that the packet bytes represent a UCI control packet. The code will not
328 // panic because UciPacketHal::to_bytes() should always be larger then the place we access.
get_opcode_from_uci_control_packet(packet: &UciPacketHal) -> u8329 fn get_opcode_from_uci_control_packet(packet: &UciPacketHal) -> u8 {
330     get_oid_from_uci_control_packet(&packet.clone().to_bytes())
331 }
332 
is_uci_control_packet(message_type: MessageType) -> bool333 fn is_uci_control_packet(message_type: MessageType) -> bool {
334     match message_type {
335         MessageType::Command
336         | MessageType::Response
337         | MessageType::Notification
338         | MessageType::ReservedForTesting1
339         | MessageType::ReservedForTesting2 => true,
340         _ => false,
341     }
342 }
343 
build_uci_control_packet( message_type: MessageType, group_id: GroupId, opcode: u8, payload: Option<Bytes>, ) -> Option<UciControlPacket>344 pub fn build_uci_control_packet(
345     message_type: MessageType,
346     group_id: GroupId,
347     opcode: u8,
348     payload: Option<Bytes>,
349 ) -> Option<UciControlPacket> {
350     if !is_uci_control_packet(message_type) {
351         error!("Only control packets are allowed, MessageType: {message_type:?}");
352         return None;
353     }
354     Some(UciControlPacketBuilder { group_id, message_type, opcode, payload }.build())
355 }
356 
357 // Ensure that the new packet fragment belong to the same packet.
is_same_control_packet(header: &UciControlPacketHeader, packet: &UciPacketHal) -> bool358 fn is_same_control_packet(header: &UciControlPacketHeader, packet: &UciPacketHal) -> bool {
359     is_uci_control_packet(header.message_type)
360         && header.message_type == packet.get_message_type()
361         && header.group_id == packet.get_group_id_or_data_packet_format().into()
362         && header.opcode == get_opcode_from_uci_control_packet(packet)
363 }
364 
365 impl UciControlPacket {
366     // For some usage, we need to get the raw payload.
to_raw_payload(self) -> Vec<u8>367     pub fn to_raw_payload(self) -> Vec<u8> {
368         self.to_bytes().slice(UCI_PACKET_HEADER_LEN..).to_vec()
369     }
370 }
371 
372 // Helper to convert from vector of |UciPacketHal| to |UciControlPacket|. An example
373 // usage is to convert a list UciPacketHAL fragments to one UciPacket, during de-fragmentation.
374 impl TryFrom<Vec<UciPacketHal>> for UciControlPacket {
375     type Error = Error;
376 
try_from(packets: Vec<UciPacketHal>) -> Result<Self>377     fn try_from(packets: Vec<UciPacketHal>) -> Result<Self> {
378         if packets.is_empty() {
379             return Err(Error::InvalidPacketError);
380         }
381 
382         // Store header info from the first packet.
383         let header = UciControlPacketHeader::new(
384             packets[0].get_message_type(),
385             packets[0].get_group_id_or_data_packet_format().into(),
386             get_opcode_from_uci_control_packet(&packets[0]),
387         )?;
388 
389         // Create the reassembled payload.
390         let mut payload_buf = BytesMut::new();
391         for packet in packets {
392             // Ensure that the new fragment is part of the same packet.
393             if !is_same_control_packet(&header, &packet) {
394                 error!("Received unexpected fragment: {:?}", packet);
395                 return Err(Error::InvalidPacketError);
396             }
397             // get payload by stripping the header.
398             payload_buf.extend_from_slice(&packet.to_bytes().slice(UCI_PACKET_HAL_HEADER_LEN..))
399         }
400 
401         // Create assembled |UciControlPacket| and convert to bytes again since we need to
402         // reparse the packet after defragmentation to get the appropriate message.
403         UciControlPacket::parse(
404             &UciControlPacketBuilder {
405                 message_type: header.message_type,
406                 group_id: header.group_id,
407                 opcode: header.opcode,
408                 payload: Some(payload_buf.into()),
409             }
410             .build()
411             .to_bytes(),
412         )
413     }
414 }
415 
416 #[derive(Debug, Clone)]
417 pub struct RawUciControlPacket {
418     pub mt: u8,
419     pub gid: u8,
420     pub oid: u8,
421     pub payload: Vec<u8>,
422 }
423 
424 impl RawUciControlPacket {
425     // Match the GID and OID to confirm the UCI packet (represented by header) is
426     // the same as the stored signature. We don't match the MT because they can be
427     // different (eg: CMD/RSP pair).
is_same_signature_bytes(&self, header: &[u8]) -> bool428     pub fn is_same_signature_bytes(&self, header: &[u8]) -> bool {
429         let gid = get_gid_from_uci_control_packet(header);
430         let oid = get_oid_from_uci_control_packet(header);
431         gid == self.gid && oid == self.oid
432     }
433 }
434 
435 // UCI Data packet functions.
is_uci_data_rcv_packet(message_type: MessageType, data_packet_format: DataPacketFormat) -> bool436 fn is_uci_data_rcv_packet(message_type: MessageType, data_packet_format: DataPacketFormat) -> bool {
437     message_type == MessageType::Data && data_packet_format == DataPacketFormat::DataRcv
438 }
439 
try_into_data_payload(packet: UciPacketHal) -> Result<Bytes>440 fn try_into_data_payload(packet: UciPacketHal) -> Result<Bytes> {
441     if is_uci_data_rcv_packet(
442         packet.get_message_type(),
443         packet.get_group_id_or_data_packet_format().try_into()?,
444     ) {
445         Ok(packet.to_bytes().slice(UCI_PACKET_HAL_HEADER_LEN..))
446     } else {
447         error!("Received unexpected data packet fragment: {:?}", packet);
448         Err(Error::InvalidPacketError)
449     }
450 }
451 
452 // Helper to convert from vector of |UciPacketHal| to |UciDataPacket|. An example
453 // usage is to convert a list UciPacketHAL fragments to one UciPacket, during de-fragmentation.
454 impl TryFrom<Vec<UciPacketHal>> for UciDataPacket {
455     type Error = Error;
456 
try_from(packets: Vec<UciPacketHal>) -> Result<Self>457     fn try_from(packets: Vec<UciPacketHal>) -> Result<Self> {
458         if packets.is_empty() {
459             return Err(Error::InvalidPacketError);
460         }
461 
462         // Create the reassembled payload.
463         let mut payload_buf = Bytes::new();
464         for packet in packets {
465             // Ensure that the fragment is a Data Rcv packet.
466             // Get payload by stripping the header.
467             payload_buf = [payload_buf, try_into_data_payload(packet)?].concat().into();
468         }
469 
470         // Create assembled |UciDataPacket| and convert to bytes again since we need to
471         // reparse the packet after defragmentation to get the appropriate message.
472         UciDataPacket::parse(
473             &UciDataPacketBuilder {
474                 message_type: MessageType::Data,
475                 data_packet_format: DataPacketFormat::DataRcv,
476                 payload: Some(payload_buf.into()),
477             }
478             .build()
479             .to_bytes(),
480         )
481     }
482 }
483 
484 // Helper to convert from |UciControlPacket| to vector of |UciControlPacketHal|s. An
485 // example usage is to do this conversion for fragmentation (from Host to UWBS).
486 impl From<UciControlPacket> for Vec<UciControlPacketHal> {
from(packet: UciControlPacket) -> Self487     fn from(packet: UciControlPacket) -> Self {
488         // Store header info.
489         let header = match UciControlPacketHeader::new(
490             packet.get_message_type(),
491             packet.get_group_id(),
492             packet.get_opcode(),
493         ) {
494             Ok(hdr) => hdr,
495             _ => {
496                 error!(
497                     "Unable to parse UciControlPacketHeader from UciControlPacket: {:?}",
498                     packet
499                 );
500                 return Vec::new();
501             }
502         };
503 
504         let mut fragments = Vec::new();
505         // get payload by stripping the header.
506         let payload = packet.to_bytes().slice(UCI_PACKET_HEADER_LEN..);
507         if payload.is_empty() {
508             fragments.push(
509                 UciControlPacketHalBuilder {
510                     message_type: header.message_type,
511                     group_id_or_data_packet_format: header.group_id.into(),
512                     opcode: header.opcode,
513                     packet_boundary_flag: PacketBoundaryFlag::Complete,
514                     payload: None,
515                 }
516                 .build(),
517             );
518         } else {
519             let mut fragments_iter = payload.chunks(MAX_PAYLOAD_LEN).peekable();
520             while let Some(fragment) = fragments_iter.next() {
521                 // Set the last fragment complete if this is last fragment.
522                 let pbf = if let Some(nxt_fragment) = fragments_iter.peek() {
523                     PacketBoundaryFlag::NotComplete
524                 } else {
525                     PacketBoundaryFlag::Complete
526                 };
527                 fragments.push(
528                     UciControlPacketHalBuilder {
529                         message_type: header.message_type,
530                         group_id_or_data_packet_format: header.group_id.into(),
531                         opcode: header.opcode,
532                         packet_boundary_flag: pbf,
533                         payload: Some(Bytes::from(fragment.to_owned())),
534                     }
535                     .build(),
536                 );
537             }
538         }
539         fragments
540     }
541 }
542 
543 // Helper to convert From<UciDataSnd> into Vec<UciDataPacketHal>. An
544 // example usage is for fragmentation in the Data Packet Tx flow.
545 impl From<UciDataSnd> for Vec<UciDataPacketHal> {
from(packet: UciDataSnd) -> Self546     fn from(packet: UciDataSnd) -> Self {
547         let mut fragments = Vec::new();
548         let dpf = packet.get_data_packet_format().into();
549 
550         // get payload by stripping the header.
551         let payload = packet.to_bytes().slice(UCI_DATA_SND_PACKET_HEADER_LEN..);
552         if payload.is_empty() {
553             fragments.push(
554                 UciDataPacketHalBuilder {
555                     group_id_or_data_packet_format: dpf,
556                     packet_boundary_flag: PacketBoundaryFlag::Complete,
557                     payload: None,
558                 }
559                 .build(),
560             );
561         } else {
562             let mut fragments_iter = payload.chunks(MAX_PAYLOAD_LEN).peekable();
563             while let Some(fragment) = fragments_iter.next() {
564                 // Set the last fragment complete if this is last fragment.
565                 let pbf = if let Some(nxt_fragment) = fragments_iter.peek() {
566                     PacketBoundaryFlag::NotComplete
567                 } else {
568                     PacketBoundaryFlag::Complete
569                 };
570                 fragments.push(
571                     UciDataPacketHalBuilder {
572                         group_id_or_data_packet_format: dpf,
573                         packet_boundary_flag: pbf,
574                         payload: Some(Bytes::from(fragment.to_owned())),
575                     }
576                     .build(),
577                 );
578             }
579         }
580         fragments
581     }
582 }
583 
584 #[derive(Default, Debug)]
585 pub struct PacketDefrager {
586     // Cache to store incoming fragmented packets in the middle of reassembly.
587     // Will be empty if there is no reassembly in progress.
588     // TODO(b/261762781): Prefer this to be UciControlPacketHal
589     control_fragment_cache: Vec<UciPacketHal>,
590     // TODO(b/261762781): Prefer this to be UciDataPacketHal
591     data_fragment_cache: Vec<UciPacketHal>,
592     // Raw packet payload bytes cache
593     raw_fragment_cache: Vec<u8>,
594 }
595 
596 pub enum UciDefragPacket {
597     Control(UciControlPacket),
598     Data(UciDataPacket),
599     Raw(Result<()>, RawUciControlPacket),
600 }
601 
602 impl PacketDefrager {
defragment_packet( &mut self, msg: &[u8], last_raw_cmd: Option<RawUciControlPacket>, ) -> Option<UciDefragPacket>603     pub fn defragment_packet(
604         &mut self,
605         msg: &[u8],
606         last_raw_cmd: Option<RawUciControlPacket>,
607     ) -> Option<UciDefragPacket> {
608         if let Some(raw_cmd) = last_raw_cmd {
609             let mt_u8 = get_mt_from_uci_packet(msg);
610             match MessageType::try_from(u8::from(mt_u8)) {
611                 Ok(mt) => match mt {
612                     // Parse only a UCI response packet as a Raw packet.
613                     MessageType::Response => {
614                         return self.defragment_raw_uci_response_packet(msg, raw_cmd);
615                     }
616                     _ => { /* Fallthrough to de-frag as a normal UCI packet below */ }
617                 },
618                 Err(_) => {
619                     error!("Rx packet from HAL has unrecognized MT={}", mt_u8);
620                     return Some(UciDefragPacket::Raw(
621                         Err(Error::InvalidPacketError),
622                         RawUciControlPacket { mt: mt_u8, gid: 0, oid: 0, payload: Vec::new() },
623                     ));
624                 }
625             };
626         }
627 
628         let packet = UciPacketHal::parse(msg)
629             .or_else(|e| {
630                 error!("Failed to parse packet: {:?}", e);
631                 Err(e)
632             })
633             .ok()?;
634 
635         let pbf = packet.get_packet_boundary_flag();
636 
637         // TODO(b/261762781): The current implementation allows for the possibility that we receive
638         // interleaved Control/Data HAL packets, and so uses separate caches for them. In the
639         // future, if we determine that interleaving is not possible, this can be simplified.
640         if is_uci_control_packet(packet.get_message_type()) {
641             // Add the incoming fragment to the control packet cache.
642             self.control_fragment_cache.push(packet);
643             if pbf == PacketBoundaryFlag::NotComplete {
644                 // Wait for remaining fragments.
645                 return None;
646             }
647 
648             // All fragments received, defragment the control packet.
649             match self.control_fragment_cache.drain(..).collect::<Vec<_>>().try_into() {
650                 Ok(packet) => Some(UciDefragPacket::Control(packet)),
651                 Err(e) => {
652                     error!("Failed to defragment control packet: {:?}", e);
653                     None
654                 }
655             }
656         } else {
657             // Add the incoming fragment to the data packet cache.
658             self.data_fragment_cache.push(packet);
659             if pbf == PacketBoundaryFlag::NotComplete {
660                 // Wait for remaining fragments.
661                 return None;
662             }
663 
664             // All fragments received, defragment the data packet.
665             match self.data_fragment_cache.drain(..).collect::<Vec<_>>().try_into() {
666                 Ok(packet) => Some(UciDefragPacket::Data(packet)),
667                 Err(e) => {
668                     error!("Failed to defragment data packet: {:?}", e);
669                     None
670                 }
671             }
672         }
673     }
674 
defragment_raw_uci_response_packet( &mut self, msg: &[u8], raw_cmd: RawUciControlPacket, ) -> Option<UciDefragPacket>675     fn defragment_raw_uci_response_packet(
676         &mut self,
677         msg: &[u8],
678         raw_cmd: RawUciControlPacket,
679     ) -> Option<UciDefragPacket> {
680         let mt_u8 = get_mt_from_uci_packet(msg);
681         let pbf = get_pbf_from_uci_packet(msg);
682         let gid = get_gid_from_uci_control_packet(msg);
683         let oid = get_oid_from_uci_control_packet(msg);
684         if raw_cmd.is_same_signature_bytes(msg) {
685             // Store only the packet payload bytes (UCI header should not be stored).
686             self.raw_fragment_cache.extend_from_slice(&msg[UCI_PACKET_HAL_HEADER_LEN..]);
687 
688             if pbf == u8::from(PacketBoundaryFlag::NotComplete) {
689                 return None;
690             }
691 
692             // All fragments received, defragment and return the Raw packet's payload bytes.
693             return Some(UciDefragPacket::Raw(
694                 Ok(()),
695                 RawUciControlPacket {
696                     mt: mt_u8,
697                     gid,
698                     oid,
699                     payload: self.raw_fragment_cache.drain(..).collect(),
700                 },
701             ));
702         } else {
703             error!(
704                 "Rx packet from HAL (MT={}, PBF={}, GID={}, OID={}) has non-matching\
705                    RawCmd signature",
706                 mt_u8, pbf, gid, oid
707             );
708             return Some(UciDefragPacket::Raw(
709                 Err(Error::InvalidPacketError),
710                 RawUciControlPacket { mt: mt_u8, gid, oid, payload: Vec::new() },
711             ));
712         }
713     }
714 }
715 
716 #[allow(dead_code)]
717 #[derive(Debug, Clone)]
718 pub struct ParsedDiagnosticNtfPacket {
719     session_token: u32,
720     sequence_number: u32,
721     frame_reports: Vec<ParsedFrameReport>,
722 }
723 
724 #[allow(dead_code)]
725 #[derive(Debug, Clone)]
726 pub struct ParsedFrameReport {
727     uwb_msg_id: u8,
728     action: u8,
729     antenna_set: u8,
730     rssi: Vec<u8>,
731     aoa: Vec<AoaMeasurement>,
732     cir: Vec<CirValue>,
733 }
734 
parse_diagnostics_ntf(evt: AndroidRangeDiagnosticsNtf) -> Result<ParsedDiagnosticNtfPacket>735 pub fn parse_diagnostics_ntf(evt: AndroidRangeDiagnosticsNtf) -> Result<ParsedDiagnosticNtfPacket> {
736     let session_token = evt.get_session_token();
737     let sequence_number = evt.get_sequence_number();
738     let mut parsed_frame_reports = Vec::new();
739     for report in evt.get_frame_reports() {
740         let mut rssi_vec = Vec::new();
741         let mut aoa_vec = Vec::new();
742         let mut cir_vec = Vec::new();
743         for tlv in &report.frame_report_tlvs {
744             match FrameReportTlvPacket::parse(
745                 &[vec![tlv.t as u8, tlv.v.len() as u8, (tlv.v.len() >> 8) as u8], tlv.v.clone()]
746                     .concat(),
747             ) {
748                 Ok(pkt) => match pkt.specialize() {
749                     FrameReportTlvPacketChild::Rssi(rssi) => {
750                         rssi_vec.append(&mut rssi.get_rssi().clone())
751                     }
752                     FrameReportTlvPacketChild::Aoa(aoa) => {
753                         aoa_vec.append(&mut aoa.get_aoa().clone())
754                     }
755                     FrameReportTlvPacketChild::Cir(cir) => {
756                         cir_vec.append(&mut cir.get_cir_value().clone())
757                     }
758                     _ => return Err(Error::InvalidPacketError),
759                 },
760                 Err(e) => {
761                     error!("Failed to parse the packet {:?}", e);
762                     return Err(Error::InvalidPacketError);
763                 }
764             }
765         }
766         parsed_frame_reports.push(ParsedFrameReport {
767             uwb_msg_id: report.uwb_msg_id,
768             action: report.action,
769             antenna_set: report.antenna_set,
770             rssi: rssi_vec,
771             aoa: aoa_vec,
772             cir: cir_vec,
773         });
774     }
775     Ok(ParsedDiagnosticNtfPacket {
776         session_token,
777         sequence_number,
778         frame_reports: parsed_frame_reports,
779     })
780 }
781 
782 #[derive(Debug, Clone, PartialEq)]
783 pub enum Controlees {
784     NoSessionKey(Vec<Controlee>),
785     ShortSessionKey(Vec<Controlee_V2_0_16_Byte_Version>),
786     LongSessionKey(Vec<Controlee_V2_0_32_Byte_Version>),
787 }
788 
789 // TODO(ziyiw): Replace these functions after making uwb_uci_packets::Controlee::write_to() public.
write_controlee(controlee: &Controlee) -> BytesMut790 pub fn write_controlee(controlee: &Controlee) -> BytesMut {
791     let mut buffer = BytesMut::new();
792     buffer.extend_from_slice(&controlee.short_address);
793     let subsession_id = controlee.subsession_id;
794     buffer.extend_from_slice(&subsession_id.to_le_bytes()[0..4]);
795     buffer
796 }
797 
write_controlee_2_0_16byte(controlee: &Controlee_V2_0_16_Byte_Version) -> BytesMut798 pub fn write_controlee_2_0_16byte(controlee: &Controlee_V2_0_16_Byte_Version) -> BytesMut {
799     let mut buffer = BytesMut::new();
800     buffer.extend_from_slice(&controlee.short_address);
801     let subsession_id = controlee.subsession_id;
802     buffer.extend_from_slice(&subsession_id.to_le_bytes()[0..4]);
803     buffer.extend_from_slice(&controlee.subsession_key);
804     buffer
805 }
806 
write_controlee_2_0_32byte(controlee: &Controlee_V2_0_32_Byte_Version) -> BytesMut807 pub fn write_controlee_2_0_32byte(controlee: &Controlee_V2_0_32_Byte_Version) -> BytesMut {
808     let mut buffer = BytesMut::new();
809     buffer.extend_from_slice(&controlee.short_address);
810     let subsession_id = controlee.subsession_id;
811     buffer.extend_from_slice(&subsession_id.to_le_bytes()[0..4]);
812     buffer.extend_from_slice(&controlee.subsession_key);
813     buffer
814 }
815 
816 /// Generate the SessionUpdateControllerMulticastListCmd packet.
817 ///
818 /// This function can build the packet with/without message control, which
819 /// is indicated by action parameter.
build_session_update_controller_multicast_list_cmd( session_token: u32, action: UpdateMulticastListAction, controlees: Controlees, ) -> Result<SessionUpdateControllerMulticastListCmd>820 pub fn build_session_update_controller_multicast_list_cmd(
821     session_token: u32,
822     action: UpdateMulticastListAction,
823     controlees: Controlees,
824 ) -> Result<SessionUpdateControllerMulticastListCmd> {
825     let mut controlees_buf = BytesMut::new();
826     match controlees {
827         Controlees::NoSessionKey(controlee_v1)
828             if action == UpdateMulticastListAction::AddControlee
829                 || action == UpdateMulticastListAction::RemoveControlee =>
830         {
831             controlees_buf.extend_from_slice(&(controlee_v1.len() as u8).to_le_bytes());
832             for controlee in controlee_v1 {
833                 controlees_buf.extend_from_slice(&write_controlee(&controlee));
834             }
835         }
836         Controlees::ShortSessionKey(controlee_v2)
837             if action == UpdateMulticastListAction::AddControleeWithShortSubSessionKey =>
838         {
839             controlees_buf.extend_from_slice(&(controlee_v2.len() as u8).to_le_bytes());
840             for controlee in controlee_v2 {
841                 controlees_buf.extend_from_slice(&write_controlee_2_0_16byte(&controlee));
842             }
843         }
844         Controlees::LongSessionKey(controlee_v2)
845             if action == UpdateMulticastListAction::AddControleeWithLongSubSessionKey =>
846         {
847             controlees_buf.extend_from_slice(&(controlee_v2.len() as u8).to_le_bytes());
848             for controlee in controlee_v2 {
849                 controlees_buf.extend_from_slice(&write_controlee_2_0_32byte(&controlee));
850             }
851         }
852         _ => return Err(Error::InvalidPacketError),
853     }
854     Ok(SessionUpdateControllerMulticastListCmdBuilder {
855         session_token,
856         action,
857         payload: Some(controlees_buf.freeze()),
858     }
859     .build())
860 }
861 
862 impl Drop for AppConfigTlv {
drop(&mut self)863     fn drop(&mut self) {
864         if self.cfg_id == AppConfigTlvType::VendorId || self.cfg_id == AppConfigTlvType::StaticStsIv
865         {
866             self.v.zeroize();
867         }
868     }
869 }
870 
871 #[cfg(test)]
872 mod tests {
873     use super::*;
874 
875     #[test]
test_parse_diagnostics_ntf()876     fn test_parse_diagnostics_ntf() {
877         let rssi_vec = vec![0x01, 0x02, 0x03];
878         let rssi = RssiBuilder { rssi: rssi_vec.clone() }.build();
879         let aoa_1 = AoaMeasurement { tdoa: 1, pdoa: 2, aoa: 3, fom: 4, t: 1 };
880         let aoa_2 = AoaMeasurement { tdoa: 5, pdoa: 6, aoa: 7, fom: 8, t: 2 };
881         let aoa = AoaBuilder { aoa: vec![aoa_1.clone(), aoa_2.clone()] }.build();
882         let cir_vec = vec![CirValue {
883             first_path_index: 1,
884             first_path_snr: 2,
885             first_path_ns: 3,
886             peak_path_index: 4,
887             peak_path_snr: 5,
888             peak_path_ns: 6,
889             first_path_sample_offset: 7,
890             samples_number: 2,
891             sample_window: vec![0, 1, 2, 3],
892         }];
893         let cir = CirBuilder { cir_value: cir_vec.clone() }.build();
894         let mut frame_reports = Vec::new();
895         let tlvs = vec![
896             FrameReportTlv { t: rssi.get_t(), v: rssi.get_rssi().to_vec() },
897             FrameReportTlv { t: aoa.get_t(), v: aoa.to_vec()[3..].to_vec() },
898             FrameReportTlv { t: cir.get_t(), v: cir.to_vec()[3..].to_vec() },
899         ];
900         let frame_report =
901             FrameReport { uwb_msg_id: 1, action: 1, antenna_set: 1, frame_report_tlvs: tlvs };
902         frame_reports.push(frame_report);
903         let packet = AndroidRangeDiagnosticsNtfBuilder {
904             session_token: 1,
905             sequence_number: 1,
906             frame_reports,
907         }
908         .build();
909         let mut parsed_packet = parse_diagnostics_ntf(packet).unwrap();
910         let parsed_frame_report = parsed_packet.frame_reports.pop().unwrap();
911         assert_eq!(rssi_vec, parsed_frame_report.rssi);
912         assert_eq!(aoa_1, parsed_frame_report.aoa[0]);
913         assert_eq!(aoa_2, parsed_frame_report.aoa[1]);
914         assert_eq!(cir_vec, parsed_frame_report.cir);
915     }
916 
917     #[test]
test_write_controlee()918     fn test_write_controlee() {
919         let short_address: [u8; 2] = [2, 3];
920         let controlee: Controlee = Controlee { short_address, subsession_id: 3 };
921         let bytes = write_controlee(&controlee);
922         let parsed_controlee = Controlee::parse(&bytes).unwrap();
923         assert_eq!(controlee, parsed_controlee);
924     }
925 
926     #[test]
test_build_multicast_update_packet()927     fn test_build_multicast_update_packet() {
928         let short_address: [u8; 2] = [0x12, 0x34];
929         let controlee = Controlee { short_address, subsession_id: 0x1324_3546 };
930         let packet: UciControlPacket = build_session_update_controller_multicast_list_cmd(
931             0x1425_3647,
932             UpdateMulticastListAction::AddControlee,
933             Controlees::NoSessionKey(vec![controlee; 1]),
934         )
935         .unwrap()
936         .into();
937         let packet_fragments: Vec<UciControlPacketHal> = packet.into();
938         let uci_packet: Vec<u8> = packet_fragments[0].clone().into();
939         assert_eq!(
940             uci_packet,
941             vec![
942                 0x21, 0x07, 0x00, 0x0c, // 2(packet info), RFU, payload length(12)
943                 0x47, 0x36, 0x25, 0x14, // 4(session id (LE))
944                 0x00, 0x01, 0x12, 0x34, // action, # controlee, 2(short address (LE))
945                 0x46, 0x35, 0x24, 0x13, // 4(subsession id (LE))
946             ]
947         );
948     }
949 
950     #[test]
test_to_raw_payload()951     fn test_to_raw_payload() {
952         let payload = vec![0x11, 0x22, 0x33];
953         let payload_clone = payload.clone();
954         let packet = UciControlPacketBuilder {
955             group_id: GroupId::Test,
956             message_type: MessageType::Response,
957             opcode: 0x5,
958             payload: Some(payload_clone.into()),
959         }
960         .build();
961 
962         assert_eq!(payload, packet.to_raw_payload());
963     }
964 
965     #[test]
test_to_raw_payload_empty()966     fn test_to_raw_payload_empty() {
967         let payload: Vec<u8> = vec![];
968         let packet = UciControlPacketBuilder {
969             group_id: GroupId::Test,
970             message_type: MessageType::Response,
971             opcode: 0x5,
972             payload: None,
973         }
974         .build();
975 
976         assert_eq!(payload, packet.to_raw_payload());
977     }
978 
979     #[cfg(test)]
980     mod tests {
981         use crate::{extract_u16, extract_u32, extract_u64, extract_u8, extract_vec};
982         #[test]
test_extract_func()983         fn test_extract_func() {
984             let bytes = [0x1, 0x3, 0x5, 0x7, 0x9, 0x2, 0x4, 0x05, 0x07, 0x09, 0x0a];
985             let mut ptr = 0;
986 
987             let u8_val = extract_u8(&bytes, &mut ptr, 1);
988             assert_eq!(u8_val, Some(0x1));
989             assert_eq!(ptr, 1);
990 
991             let u16_val = extract_u16(&bytes, &mut ptr, 2);
992             assert_eq!(u16_val, Some(0x0503));
993             assert_eq!(ptr, 3);
994 
995             let u32_val = extract_u32(&bytes, &mut ptr, 3);
996             assert_eq!(u32_val, Some(0x020907));
997             assert_eq!(ptr, 6);
998 
999             let u64_val = extract_u64(&bytes, &mut ptr, 5);
1000             assert_eq!(u64_val, Some(0x0a09070504));
1001             assert_eq!(ptr, 11);
1002 
1003             let vec = extract_vec(&bytes, &mut ptr, 3);
1004             assert_eq!(vec, None);
1005             assert_eq!(ptr, 11);
1006         }
1007     }
1008 
1009     #[test]
test_short_dltdoa_ranging_measurement()1010     fn test_short_dltdoa_ranging_measurement() {
1011         let bytes = [
1012             // All Fields in Little Endian (LE)
1013             // First measurement
1014             0x0a, 0x01, 0x33, 0x05, // 2(Mac address), Status, Message Type
1015             0x33, 0x05, 0x02, 0x05, // 2(Message control), 2(Block Index)
1016             0x07, 0x09, 0x0a, 0x01, // Round Index, NLoS, 2(AoA Azimuth)
1017             0x02, 0x05, 0x07, 0x09, // AoA Azimuth FOM, 2(AoA Elevation), AoA Elevation FOM
1018             0x0a, 0x01, 0x02, 0x05, // RSSI, 3(Tx Timestamp..)
1019             0x07, 0x09, 0x0a, 0x01, // 4(Tx Timestamp..)
1020             0x02, 0x05, 0x07, 0x09, // Tx Timestamp, 3(Rx Timestamp..)
1021             0x05, 0x07, 0x09, 0x0a, // 2(Rx Timestamp), 2(Anchor Cfo)
1022             0x01, 0x02, 0x05, 0x07, // 2(Cfo), 2(Initiator Reply Time..)
1023             0x09, 0x05, 0x07, 0x09, // 2(Initiator Reply Time), 2(Responder Reply Time..)
1024             0x0a, 0x01, 0x02, 0x05, // 2(Responder Reply Time), 2(Initiator-Responder ToF)
1025             0x07, 0x09, 0x07, 0x09, // 4(Anchor Location..)
1026             0x05, 0x07, 0x09, 0x0a, // 4(Anchor Location..)
1027             0x01, 0x02, 0x05, 0x07, // 2(Anchor Location..), 2(Active Ranging Rounds..)
1028             0x09, 0x0a, 0x01, 0x02, // 4(Active Ranging Rounds..)
1029             0x05, 0x07, 0x09, 0x05, // 4(Active Ranging Rounds)
1030             // Second measurement
1031             0x0a, 0x01, 0x33, 0x05, // 2(Mac address), Status, Message Type
1032             0x33, 0x05, 0x02, 0x05, // 2(Message control), 2(Block Index)
1033             0x07, 0x09, 0x0a, 0x01, // Round Index, NLoS, 2(AoA Azimuth)
1034             0x02, 0x05, 0x07, 0x09, // AoA Azimuth FOM, 2(AoA Elevation), AoA Elevation FOM
1035             0x0a, 0x01, 0x02, 0x05, // RSSI, 3(Tx Timestamp..)
1036             0x07, 0x09, 0x0a, 0x01, // 4(Tx Timestamp..)
1037             0x02, 0x05, 0x07, 0x09, // Tx Timestamp, 3(Rx Timestamp..)
1038             0x05, 0x07, 0x09, 0x0a, // 2(Rx Timestamp), 2(Anchor Cfo)
1039             0x01, 0x02, 0x05, 0x07, // 2(Cfo), 2(Initiator Reply Time..)
1040             0x09, 0x05, 0x07, 0x09, // 2(Initiator Reply Time), 2(Responder Reply Time..)
1041             0x0a, 0x01, 0x02, 0x05, // 2(Responder Reply Time), 2(Initiator-Responder ToF)
1042             0x07, 0x09, 0x07, 0x09, // 4(Anchor Location..)
1043             0x05, 0x07, 0x09, 0x0a, // 4(Anchor Location..)
1044             0x01, 0x02, 0x05, 0x07, // 2(Anchor Location..), 2(Active Ranging Rounds..)
1045             0x09, 0x0a, 0x01, 0x02, // 4(Active Ranging Rounds..)
1046             0x05, 0x07, 0x09, 0x05, // 4(Active Ranging Rounds)
1047         ];
1048 
1049         let measurements = ShortAddressDlTdoaRangingMeasurement::parse(&bytes, 2).unwrap();
1050         assert_eq!(measurements.len(), 2);
1051         let measurement_1 = &measurements[0].measurement;
1052         let mac_address_1 = &measurements[0].mac_address;
1053         assert_eq!(*mac_address_1, 0x010a);
1054         assert_eq!(measurement_1.status, 0x33);
1055         assert_eq!(measurement_1.message_type, 0x05);
1056         assert_eq!(measurement_1.message_control, 0x0533);
1057         assert_eq!(measurement_1.block_index, 0x0502);
1058         assert_eq!(measurement_1.round_index, 0x07);
1059         assert_eq!(measurement_1.nlos, 0x09);
1060         assert_eq!(measurement_1.aoa_azimuth, 0x010a);
1061         assert_eq!(measurement_1.aoa_azimuth_fom, 0x02);
1062         assert_eq!(measurement_1.aoa_elevation, 0x0705);
1063         assert_eq!(measurement_1.aoa_elevation_fom, 0x09);
1064         assert_eq!(measurement_1.rssi, 0x0a);
1065         assert_eq!(measurement_1.tx_timestamp, 0x02010a0907050201);
1066         assert_eq!(measurement_1.rx_timestamp, 0x0705090705);
1067         assert_eq!(measurement_1.anchor_cfo, 0x0a09);
1068         assert_eq!(measurement_1.cfo, 0x0201);
1069         assert_eq!(measurement_1.initiator_reply_time, 0x05090705);
1070         assert_eq!(measurement_1.responder_reply_time, 0x010a0907);
1071         assert_eq!(measurement_1.initiator_responder_tof, 0x0502);
1072         assert_eq!(
1073             measurement_1.dt_anchor_location,
1074             vec![0x07, 0x09, 0x07, 0x09, 0x05, 0x07, 0x09, 0x0a, 0x01, 0x02]
1075         );
1076         assert_eq!(
1077             measurement_1.ranging_rounds,
1078             vec![0x05, 0x07, 0x09, 0x0a, 0x01, 0x02, 0x05, 0x07, 0x09, 0x05,]
1079         );
1080 
1081         let measurement_2 = &measurements[1].measurement;
1082         let mac_address_2 = &measurements[1].mac_address;
1083         assert_eq!(*mac_address_2, 0x010a);
1084         assert_eq!(measurement_2.status, 0x33);
1085         assert_eq!(measurement_2.message_type, 0x05);
1086         assert_eq!(measurement_2.message_control, 0x0533);
1087         assert_eq!(measurement_2.block_index, 0x0502);
1088         assert_eq!(measurement_2.round_index, 0x07);
1089         assert_eq!(measurement_2.nlos, 0x09);
1090         assert_eq!(measurement_2.aoa_azimuth, 0x010a);
1091         assert_eq!(measurement_2.aoa_azimuth_fom, 0x02);
1092         assert_eq!(measurement_2.aoa_elevation, 0x0705);
1093         assert_eq!(measurement_2.aoa_elevation_fom, 0x09);
1094         assert_eq!(measurement_2.rssi, 0x0a);
1095         assert_eq!(measurement_2.tx_timestamp, 0x02010a0907050201);
1096         assert_eq!(measurement_2.rx_timestamp, 0x0705090705);
1097         assert_eq!(measurement_2.anchor_cfo, 0x0a09);
1098         assert_eq!(measurement_2.cfo, 0x0201);
1099         assert_eq!(measurement_2.initiator_reply_time, 0x05090705);
1100         assert_eq!(measurement_2.responder_reply_time, 0x010a0907);
1101         assert_eq!(measurement_2.initiator_responder_tof, 0x0502);
1102         assert_eq!(
1103             measurement_1.dt_anchor_location,
1104             vec![0x07, 0x09, 0x07, 0x09, 0x05, 0x07, 0x09, 0x0a, 0x01, 0x02]
1105         );
1106         assert_eq!(
1107             measurement_1.ranging_rounds,
1108             vec![0x05, 0x07, 0x09, 0x0a, 0x01, 0x02, 0x05, 0x07, 0x09, 0x05,]
1109         );
1110     }
1111 
1112     #[test]
test_extended_dltdoa_ranging_measurement()1113     fn test_extended_dltdoa_ranging_measurement() {
1114         let bytes = [
1115             // All Fields in Little Endian (LE)
1116             /* First measurement  */
1117             0x0a, 0x01, 0x33, 0x05, // 4(Mac address..)
1118             0x33, 0x05, 0x02, 0x05, // 4(Mac address)
1119             0x07, 0x09, 0x0a, 0x01, // Status, Message Type, 2(Message control),
1120             0x02, 0x05, 0x07, 0x09, // 2(Block Index), Round Index, NLoS,
1121             0x0a, 0x01, 0x02, 0x05, // 2(AoA Azimuth), AoA Azimuth FOM, 1(AoA Elevation..)
1122             0x07, 0x09, 0x0a, // 1(AoA Elevation), AoA Elevation FOM, RSSI,
1123             0x01, 0x02, 0x05, 0x07, // 4(Tx Timestamp..)
1124             0x09, 0x05, 0x07, 0x09, // 4(Tx Timestamp),
1125             0x0a, 0x01, 0x02, 0x05, // 4(Rx Timestamp..)
1126             0x07, 0x09, 0x05, 0x07, // 4(Rx Timestamp)
1127             0x09, 0x0a, 0x01, 0x02, // 2(Anchor Cfo), 2(Cfo),
1128             0x05, 0x07, 0x09, 0x05, // 4(Initiator Reply Time)
1129             0x07, 0x09, 0x0a, 0x01, // 4(Responder Reply Time),
1130             0x02, 0x05, 0x02, 0x05, // 2(Initiator-Responder ToF), 2(Active Ranging Rounds)
1131         ];
1132 
1133         let measurements = ExtendedAddressDlTdoaRangingMeasurement::parse(&bytes, 1).unwrap();
1134         assert_eq!(measurements.len(), 1);
1135         let measurement = &measurements[0].measurement;
1136         let mac_address = &measurements[0].mac_address;
1137         assert_eq!(*mac_address, 0x050205330533010a);
1138         assert_eq!(measurement.message_control, 0x010a);
1139         assert_eq!(measurement.block_index, 0x0502);
1140         assert_eq!(measurement.round_index, 0x07);
1141         assert_eq!(measurement.nlos, 0x09);
1142         assert_eq!(measurement.aoa_azimuth, 0x010a);
1143         assert_eq!(measurement.aoa_azimuth_fom, 0x02);
1144         assert_eq!(measurement.aoa_elevation, 0x0705);
1145         assert_eq!(measurement.aoa_elevation_fom, 0x09);
1146         assert_eq!(measurement.rssi, 0x0a);
1147         assert_eq!(measurement.tx_timestamp, 0x0907050907050201);
1148         assert_eq!(measurement.rx_timestamp, 0x070509070502010a);
1149         assert_eq!(measurement.anchor_cfo, 0x0a09);
1150         assert_eq!(measurement.cfo, 0x0201);
1151         assert_eq!(measurement.initiator_reply_time, 0x05090705);
1152         assert_eq!(measurement.responder_reply_time, 0x010a0907);
1153         assert_eq!(measurement.initiator_responder_tof, 0x0502);
1154         assert_eq!(measurement.dt_anchor_location, vec![]);
1155         assert_eq!(measurement.ranging_rounds, vec![0x02, 0x05]);
1156     }
1157 }
1158