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 // Radar field lengths
57 pub const UCI_RADAR_SEQUENCE_NUMBER_LEN: usize = 4;
58 pub const UCI_RADAR_TIMESTAMP_LEN: usize = 4;
59 pub const UCI_RADAR_VENDOR_DATA_LEN_LEN: usize = 1;
60
61 #[derive(Debug, Clone, PartialEq, FromPrimitive)]
62 pub enum TimeStampLength {
63 Timestamp40Bit = 0x0,
64 Timestamp64Bit = 0x1,
65 }
66
67 #[derive(Debug, Clone, PartialEq, FromPrimitive)]
68 pub enum DTAnchorLocationType {
69 NotIncluded = 0x0,
70 Wgs84 = 0x1,
71 Relative = 0x2,
72 }
73
74 #[allow(dead_code)]
75 #[derive(Debug, Clone, PartialEq)]
76 pub struct DlTdoaRangingMeasurement {
77 pub status: u8,
78 pub message_type: u8,
79 pub message_control: u16,
80 pub block_index: u16,
81 pub round_index: u8,
82 pub nlos: u8,
83 pub aoa_azimuth: u16,
84 pub aoa_azimuth_fom: u8,
85 pub aoa_elevation: u16,
86 pub aoa_elevation_fom: u8,
87 pub rssi: u8,
88 pub tx_timestamp: u64,
89 pub rx_timestamp: u64,
90 pub anchor_cfo: u16,
91 pub cfo: u16,
92 pub initiator_reply_time: u32,
93 pub responder_reply_time: u32,
94 pub initiator_responder_tof: u16,
95 pub dt_anchor_location: Vec<u8>,
96 pub ranging_rounds: Vec<u8>,
97 total_size: usize,
98 }
99
100 impl DlTdoaRangingMeasurement {
parse_one(bytes: &[u8]) -> Option<Self>101 pub fn parse_one(bytes: &[u8]) -> Option<Self> {
102 let mut ptr = 0;
103 let status = extract_u8(bytes, &mut ptr, 1)?;
104 let message_type = extract_u8(bytes, &mut ptr, 1)?;
105 let message_control = extract_u16(bytes, &mut ptr, 2)?;
106 let block_index = extract_u16(bytes, &mut ptr, 2)?;
107 let round_index = extract_u8(bytes, &mut ptr, 1)?;
108 let nlos = extract_u8(bytes, &mut ptr, 1)?;
109 let aoa_azimuth = extract_u16(bytes, &mut ptr, 2)?;
110 let aoa_azimuth_fom = extract_u8(bytes, &mut ptr, 1)?;
111 let aoa_elevation = extract_u16(bytes, &mut ptr, 2)?;
112 let aoa_elevation_fom = extract_u8(bytes, &mut ptr, 1)?;
113 let rssi = extract_u8(bytes, &mut ptr, 1)?;
114 let tx_timestamp_length = (message_control >> 1) & 0x1;
115 let tx_timestamp = match TimeStampLength::from_u16(tx_timestamp_length)? {
116 TimeStampLength::Timestamp40Bit => extract_u64(bytes, &mut ptr, 5)?,
117 TimeStampLength::Timestamp64Bit => extract_u64(bytes, &mut ptr, 8)?,
118 };
119 let rx_timestamp_length = (message_control >> 3) & 0x1;
120 let rx_timestamp = match TimeStampLength::from_u16(rx_timestamp_length)? {
121 TimeStampLength::Timestamp40Bit => extract_u64(bytes, &mut ptr, 5)?,
122 TimeStampLength::Timestamp64Bit => extract_u64(bytes, &mut ptr, 8)?,
123 };
124 let anchor_cfo = extract_u16(bytes, &mut ptr, 2)?;
125 let cfo = extract_u16(bytes, &mut ptr, 2)?;
126 let initiator_reply_time = extract_u32(bytes, &mut ptr, 4)?;
127 let responder_reply_time = extract_u32(bytes, &mut ptr, 4)?;
128 let initiator_responder_tof = extract_u16(bytes, &mut ptr, 2)?;
129 let dt_location_type = (message_control >> 5) & 0x3;
130 let dt_anchor_location = match DTAnchorLocationType::from_u16(dt_location_type)? {
131 DTAnchorLocationType::Wgs84 => extract_vec(bytes, &mut ptr, 12)?,
132 DTAnchorLocationType::Relative => extract_vec(bytes, &mut ptr, 10)?,
133 _ => vec![],
134 };
135 let active_ranging_rounds = ((message_control >> 7) & 0xf) as u8;
136 let ranging_round = extract_vec(bytes, &mut ptr, active_ranging_rounds as usize)?;
137
138 Some(DlTdoaRangingMeasurement {
139 status,
140 message_type,
141 message_control,
142 block_index,
143 round_index,
144 nlos,
145 aoa_azimuth,
146 aoa_azimuth_fom,
147 aoa_elevation,
148 aoa_elevation_fom,
149 rssi,
150 tx_timestamp,
151 rx_timestamp,
152 anchor_cfo,
153 cfo,
154 initiator_reply_time,
155 responder_reply_time,
156 initiator_responder_tof,
157 dt_anchor_location: dt_anchor_location.to_vec(),
158 ranging_rounds: ranging_round.to_vec(),
159 total_size: ptr,
160 })
161 }
get_total_size(&self) -> usize162 pub fn get_total_size(&self) -> usize {
163 self.total_size
164 }
165 }
166
167 #[derive(Debug, Clone, PartialEq)]
168 pub struct ShortAddressDlTdoaRangingMeasurement {
169 pub mac_address: u16,
170 pub measurement: DlTdoaRangingMeasurement,
171 }
172
173 impl ShortAddressDlTdoaRangingMeasurement {
174 /// Parse the `payload` byte buffer from PDL to the vector of measurement.
parse(bytes: &[u8], no_of_ranging_measurement: u8) -> Option<Vec<Self>>175 pub fn parse(bytes: &[u8], no_of_ranging_measurement: u8) -> Option<Vec<Self>> {
176 let mut ptr = 0;
177 let mut measurements = vec![];
178 let mut count = 0;
179 while (count < no_of_ranging_measurement) {
180 let mac_address = extract_u16(bytes, &mut ptr, 2)?;
181 let rem = &bytes[ptr..];
182 let measurement = DlTdoaRangingMeasurement::parse_one(rem);
183 match measurement {
184 Some(measurement) => {
185 ptr += measurement.get_total_size();
186 measurements
187 .push(ShortAddressDlTdoaRangingMeasurement { mac_address, measurement });
188 count = count + 1;
189 }
190 None => return None,
191 }
192 }
193 Some(measurements)
194 }
195 }
196
197 #[derive(Debug, Clone, PartialEq)]
198 pub struct ExtendedAddressDlTdoaRangingMeasurement {
199 pub mac_address: u64,
200 pub measurement: DlTdoaRangingMeasurement,
201 }
202
203 impl ExtendedAddressDlTdoaRangingMeasurement {
204 /// Parse the `payload` byte buffer from PDL to the vector of measurement.
parse(bytes: &[u8], no_of_ranging_measurement: u8) -> Option<Vec<Self>>205 pub fn parse(bytes: &[u8], no_of_ranging_measurement: u8) -> Option<Vec<Self>> {
206 let mut ptr = 0;
207 let mut measurements = vec![];
208 let mut count = 0;
209 while (count < no_of_ranging_measurement) {
210 let mac_address = extract_u64(bytes, &mut ptr, 8)?;
211 let rem = &bytes[ptr..];
212 let measurement = DlTdoaRangingMeasurement::parse_one(rem);
213 match measurement {
214 Some(measurement) => {
215 ptr += measurement.get_total_size();
216 measurements
217 .push(ExtendedAddressDlTdoaRangingMeasurement { mac_address, measurement });
218 count = count + 1;
219 }
220 None => return None,
221 }
222 }
223 Some(measurements)
224 }
225 }
226
extract_vec(bytes: &[u8], ptr: &mut usize, consumed_size: usize) -> Option<Vec<u8>>227 pub fn extract_vec(bytes: &[u8], ptr: &mut usize, consumed_size: usize) -> Option<Vec<u8>> {
228 if bytes.len() < *ptr + consumed_size {
229 return None;
230 }
231
232 let res = bytes[*ptr..*ptr + consumed_size].to_vec();
233 *ptr += consumed_size;
234 Some(res)
235 }
236
237 /// Generate the function that extracts the value from byte buffers.
238 macro_rules! generate_extract_func {
239 ($func_name:ident, $type:ty) => {
240 /// Extract the value from |byte[ptr..ptr + consumed_size]| in little endian.
241 fn $func_name(bytes: &[u8], ptr: &mut usize, consumed_size: usize) -> Option<$type> {
242 const type_size: usize = std::mem::size_of::<$type>();
243 if consumed_size > type_size {
244 return None;
245 }
246
247 let extracted_bytes = extract_vec(bytes, ptr, consumed_size)?;
248 let mut le_bytes = [0; type_size];
249 le_bytes[0..consumed_size].copy_from_slice(&extracted_bytes);
250 Some(<$type>::from_le_bytes(le_bytes))
251 }
252 };
253 }
254
255 generate_extract_func!(extract_u8, u8);
256 generate_extract_func!(extract_u16, u16);
257 generate_extract_func!(extract_u32, u32);
258 generate_extract_func!(extract_u64, u64);
259
260 // The GroupIdOrDataPacketFormat enum has all the values defined in both the GroupId and
261 // DataPacketFormat enums. It represents the same bits in UCI packet header - the GID field in
262 // a UCI control packet, and the DataPacketFormat field in a UCI data packet. Hence the unwrap()
263 // calls in the conversions below should always succeed (as long as care is taken in future, to
264 // keep the two enums in sync, for any additional values defined in the UCI spec).
265 impl From<GroupId> for GroupIdOrDataPacketFormat {
from(gid: GroupId) -> Self266 fn from(gid: GroupId) -> Self {
267 GroupIdOrDataPacketFormat::try_from(u8::from(gid)).unwrap()
268 }
269 }
270
271 impl From<GroupIdOrDataPacketFormat> for GroupId {
from(gid_or_dpf: GroupIdOrDataPacketFormat) -> Self272 fn from(gid_or_dpf: GroupIdOrDataPacketFormat) -> Self {
273 GroupId::try_from(u8::from(gid_or_dpf)).unwrap()
274 }
275 }
276
277 impl From<DataPacketFormat> for GroupIdOrDataPacketFormat {
from(dpf: DataPacketFormat) -> Self278 fn from(dpf: DataPacketFormat) -> Self {
279 GroupIdOrDataPacketFormat::try_from(u8::from(dpf)).unwrap()
280 }
281 }
282
283 // The GroupIdOrDataPacketFormat enum has more values defined (for the GroupId bits) than the
284 // DataPacketFormat enum. Hence this is implemented as TryFrom() instead of From().
285 impl TryFrom<GroupIdOrDataPacketFormat> for DataPacketFormat {
286 type Error = DecodeError;
287
try_from(gid_or_dpf: GroupIdOrDataPacketFormat) -> Result<Self, DecodeError>288 fn try_from(gid_or_dpf: GroupIdOrDataPacketFormat) -> Result<Self, DecodeError> {
289 DataPacketFormat::try_from(u8::from(gid_or_dpf)).or(Err(DecodeError::InvalidPacketError))
290 }
291 }
292
293 // Container for UCI packet header fields.
294 struct UciControlPacketHeader {
295 message_type: MessageType,
296 group_id: GroupId,
297 opcode: u8,
298 }
299
300 impl UciControlPacketHeader {
new(message_type: MessageType, group_id: GroupId, opcode: u8) -> Result<Self, DecodeError>301 fn new(message_type: MessageType, group_id: GroupId, opcode: u8) -> Result<Self, DecodeError> {
302 if !is_uci_control_packet(message_type) {
303 return Err(DecodeError::InvalidPacketError);
304 }
305
306 Ok(UciControlPacketHeader {
307 message_type: message_type,
308 group_id: group_id,
309 opcode: opcode,
310 })
311 }
312 }
313
314 // Helper methods to extract the UCI Packet header fields.
get_mt_from_uci_packet(packet: &[u8]) -> u8315 fn get_mt_from_uci_packet(packet: &[u8]) -> u8 {
316 (packet[UCI_HEADER_MT_BYTE_POSITION] >> UCI_HEADER_MT_BIT_SHIFT) & UCI_HEADER_MT_MASK
317 }
318
get_pbf_from_uci_packet(packet: &[u8]) -> u8319 fn get_pbf_from_uci_packet(packet: &[u8]) -> u8 {
320 (packet[UCI_HEADER_PBF_BYTE_POSITION] >> UCI_HEADER_PBF_BIT_SHIFT) & UCI_HEADER_PBF_MASK
321 }
322
get_gid_from_uci_control_packet(packet: &[u8]) -> u8323 fn get_gid_from_uci_control_packet(packet: &[u8]) -> u8 {
324 packet[UCI_CONTROL_HEADER_GID_BYTE_POSITION] & UCI_CONTROL_HEADER_GID_MASK
325 }
326
get_oid_from_uci_control_packet(packet: &[u8]) -> u8327 fn get_oid_from_uci_control_packet(packet: &[u8]) -> u8 {
328 packet[UCI_CONTROL_HEADER_OID_BYTE_POSITION] & UCI_CONTROL_HEADER_OID_MASK
329 }
330
331 // This function parses the packet bytes to return the Control Packet Opcode (OID) field. The
332 // caller should check that the packet bytes represent a UCI control packet. The code will not
333 // panic because UciPacketHal::encode_to_bytes() should always be larger then the place we access.
get_opcode_from_uci_control_packet(packet: &UciPacketHal) -> u8334 fn get_opcode_from_uci_control_packet(packet: &UciPacketHal) -> u8 {
335 get_oid_from_uci_control_packet(&packet.encode_to_bytes().unwrap())
336 }
337
is_uci_control_packet(message_type: MessageType) -> bool338 fn is_uci_control_packet(message_type: MessageType) -> bool {
339 match message_type {
340 MessageType::Command
341 | MessageType::Response
342 | MessageType::Notification
343 | MessageType::ReservedForTesting1
344 | MessageType::ReservedForTesting2 => true,
345 _ => false,
346 }
347 }
348
build_uci_control_packet( message_type: MessageType, group_id: GroupId, opcode: u8, payload: Option<Bytes>, ) -> Option<UciControlPacket>349 pub fn build_uci_control_packet(
350 message_type: MessageType,
351 group_id: GroupId,
352 opcode: u8,
353 payload: Option<Bytes>,
354 ) -> Option<UciControlPacket> {
355 if !is_uci_control_packet(message_type) {
356 error!("Only control packets are allowed, MessageType: {message_type:?}");
357 return None;
358 }
359 Some(UciControlPacketBuilder { group_id, message_type, opcode, payload }.build())
360 }
361
362 // Ensure that the new packet fragment belong to the same packet.
is_same_control_packet(header: &UciControlPacketHeader, packet: &UciPacketHal) -> bool363 fn is_same_control_packet(header: &UciControlPacketHeader, packet: &UciPacketHal) -> bool {
364 is_uci_control_packet(header.message_type)
365 && header.message_type == packet.get_message_type()
366 && header.group_id == packet.get_group_id_or_data_packet_format().into()
367 && header.opcode == get_opcode_from_uci_control_packet(packet)
368 }
369
is_device_state_err_control_packet(packet: &UciPacketHal) -> bool370 fn is_device_state_err_control_packet(packet: &UciPacketHal) -> bool {
371 packet.get_message_type() == MessageType::Notification.into()
372 && packet.get_group_id_or_data_packet_format() == GroupIdOrDataPacketFormat::Core.into()
373 && get_opcode_from_uci_control_packet(packet) == CoreOpCode::CoreDeviceStatusNtf.into()
374 && packet.encode_to_vec().unwrap()[UCI_PACKET_HAL_HEADER_LEN]
375 == DeviceState::DeviceStateError.into()
376 }
377
378 impl UciControlPacket {
379 // For some usage, we need to get the raw payload.
to_raw_payload(self) -> Vec<u8>380 pub fn to_raw_payload(self) -> Vec<u8> {
381 self.encode_to_bytes().unwrap().slice(UCI_PACKET_HEADER_LEN..).to_vec()
382 }
383 }
384
385 // Helper to convert from vector of |UciPacketHal| to |UciControlPacket|. An example
386 // usage is to convert a list UciPacketHAL fragments to one UciPacket, during de-fragmentation.
387 impl TryFrom<Vec<UciPacketHal>> for UciControlPacket {
388 type Error = DecodeError;
389
try_from(packets: Vec<UciPacketHal>) -> Result<Self, DecodeError>390 fn try_from(packets: Vec<UciPacketHal>) -> Result<Self, DecodeError> {
391 if packets.is_empty() {
392 return Err(DecodeError::InvalidPacketError);
393 }
394
395 // Store header info from the first packet.
396 let header = UciControlPacketHeader::new(
397 packets[0].get_message_type(),
398 packets[0].get_group_id_or_data_packet_format().into(),
399 get_opcode_from_uci_control_packet(&packets[0]),
400 )?;
401
402 // Create the reassembled payload.
403 let mut payload_buf = BytesMut::new();
404 for packet in packets {
405 // Ensure that the new fragment is part of the same packet.
406 if !is_same_control_packet(&header, &packet) {
407 // if DEVICE_STATE_ERROR notification is received while waiting for remaining fragments,
408 // process it and send to upper layer for device recovery
409 if is_device_state_err_control_packet(&packet) {
410 error!("Received device reset error: {:?}", packet);
411 return UciControlPacket::parse(
412 &UciControlPacketBuilder {
413 message_type: packet.get_message_type(),
414 group_id: packet.get_group_id_or_data_packet_format().into(),
415 opcode: get_opcode_from_uci_control_packet(&packet),
416 payload: Some(
417 packet
418 .encode_to_bytes()
419 .unwrap()
420 .slice(UCI_PACKET_HAL_HEADER_LEN..),
421 ),
422 }
423 .build()
424 .encode_to_bytes()
425 .unwrap(),
426 );
427 }
428 error!("Received unexpected fragment: {:?}", packet);
429 return Err(DecodeError::InvalidPacketError);
430 }
431 // get payload by stripping the header.
432 payload_buf.extend_from_slice(
433 &packet.encode_to_bytes().unwrap().slice(UCI_PACKET_HAL_HEADER_LEN..),
434 )
435 }
436
437 // Create assembled |UciControlPacket| and convert to bytes again since we need to
438 // reparse the packet after defragmentation to get the appropriate message.
439 UciControlPacket::parse(
440 &UciControlPacketBuilder {
441 message_type: header.message_type,
442 group_id: header.group_id,
443 opcode: header.opcode,
444 payload: Some(payload_buf.into()),
445 }
446 .build()
447 .encode_to_bytes()
448 .unwrap(),
449 )
450 }
451 }
452
453 #[derive(Debug, Clone)]
454 pub struct RawUciControlPacket {
455 pub mt: u8,
456 pub gid: u8,
457 pub oid: u8,
458 pub payload: Vec<u8>,
459 }
460
461 impl RawUciControlPacket {
462 // Match the GID and OID to confirm the UCI packet (represented by header) is
463 // the same as the stored signature. We don't match the MT because they can be
464 // different (eg: CMD/RSP pair).
is_same_signature_bytes(&self, header: &[u8]) -> bool465 pub fn is_same_signature_bytes(&self, header: &[u8]) -> bool {
466 let gid = get_gid_from_uci_control_packet(header);
467 let oid = get_oid_from_uci_control_packet(header);
468 gid == self.gid && oid == self.oid
469 }
470 }
471
is_uci_data_packet(message_type: MessageType) -> bool472 fn is_uci_data_packet(message_type: MessageType) -> bool {
473 message_type == MessageType::Data
474 }
475
is_data_rcv_or_radar_format(data_packet_format: DataPacketFormat) -> bool476 fn is_data_rcv_or_radar_format(data_packet_format: DataPacketFormat) -> bool {
477 data_packet_format == DataPacketFormat::DataRcv
478 || data_packet_format == DataPacketFormat::RadarDataMessage
479 }
480
try_into_data_payload( packet: UciPacketHal, expected_data_packet_format: DataPacketFormat, ) -> Result<Bytes, DecodeError>481 fn try_into_data_payload(
482 packet: UciPacketHal,
483 expected_data_packet_format: DataPacketFormat,
484 ) -> Result<Bytes, DecodeError> {
485 let dpf: DataPacketFormat = packet.get_group_id_or_data_packet_format().try_into()?;
486 if is_uci_data_packet(packet.get_message_type()) && dpf == expected_data_packet_format {
487 Ok(packet.encode_to_bytes().unwrap().slice(UCI_PACKET_HAL_HEADER_LEN..))
488 } else {
489 error!("Received unexpected data packet fragment: {:?}", packet);
490 Err(DecodeError::InvalidPacketError)
491 }
492 }
493
494 // Helper to convert from vector of |UciPacketHal| to |UciDataPacket|. An example
495 // usage is to convert a list UciPacketHAL fragments to one UciPacket, during de-fragmentation.
496 impl TryFrom<Vec<UciPacketHal>> for UciDataPacket {
497 type Error = DecodeError;
498
try_from(packets: Vec<UciPacketHal>) -> Result<Self, DecodeError>499 fn try_from(packets: Vec<UciPacketHal>) -> Result<Self, DecodeError> {
500 if packets.is_empty() {
501 return Err(DecodeError::InvalidPacketError);
502 }
503
504 let dpf: DataPacketFormat = packets[0].get_group_id_or_data_packet_format().try_into()?;
505 if !is_data_rcv_or_radar_format(dpf) {
506 error!("Unexpected data packet format {:?}", dpf);
507 }
508
509 // Create the reassembled payload.
510 let mut payload_buf = Bytes::new();
511 for packet in packets {
512 // Ensure that the fragment is a Data Rcv packet.
513 // Get payload by stripping the header.
514 payload_buf = [payload_buf, try_into_data_payload(packet, dpf)?].concat().into();
515 }
516
517 // Create assembled |UciDataPacket| and convert to bytes again since we need to
518 // reparse the packet after defragmentation to get the appropriate message.
519 UciDataPacket::parse(
520 &UciDataPacketBuilder {
521 message_type: MessageType::Data,
522 data_packet_format: dpf,
523 payload: Some(payload_buf.into()),
524 }
525 .build()
526 .encode_to_bytes()
527 .unwrap(),
528 )
529 }
530 }
531
532 // Helper to convert from |UciControlPacket| to vector of |UciControlPacketHal|s. An
533 // example usage is to do this conversion for fragmentation (from Host to UWBS).
534 impl From<UciControlPacket> for Vec<UciControlPacketHal> {
from(packet: UciControlPacket) -> Self535 fn from(packet: UciControlPacket) -> Self {
536 // Store header info.
537 let header = match UciControlPacketHeader::new(
538 packet.get_message_type(),
539 packet.get_group_id(),
540 packet.get_opcode(),
541 ) {
542 Ok(hdr) => hdr,
543 _ => {
544 error!(
545 "Unable to parse UciControlPacketHeader from UciControlPacket: {:?}",
546 packet
547 );
548 return Vec::new();
549 }
550 };
551
552 let mut fragments = Vec::new();
553 // get payload by stripping the header.
554 let payload = packet.encode_to_bytes().unwrap().slice(UCI_PACKET_HEADER_LEN..);
555 if payload.is_empty() {
556 fragments.push(
557 UciControlPacketHalBuilder {
558 message_type: header.message_type,
559 group_id_or_data_packet_format: header.group_id.into(),
560 opcode: header.opcode,
561 packet_boundary_flag: PacketBoundaryFlag::Complete,
562 payload: None,
563 }
564 .build(),
565 );
566 } else {
567 let mut fragments_iter = payload.chunks(MAX_PAYLOAD_LEN).peekable();
568 while let Some(fragment) = fragments_iter.next() {
569 // Set the last fragment complete if this is last fragment.
570 let pbf = if let Some(nxt_fragment) = fragments_iter.peek() {
571 PacketBoundaryFlag::NotComplete
572 } else {
573 PacketBoundaryFlag::Complete
574 };
575 fragments.push(
576 UciControlPacketHalBuilder {
577 message_type: header.message_type,
578 group_id_or_data_packet_format: header.group_id.into(),
579 opcode: header.opcode,
580 packet_boundary_flag: pbf,
581 payload: Some(Bytes::from(fragment.to_owned())),
582 }
583 .build(),
584 );
585 }
586 }
587 fragments
588 }
589 }
590
591 // Helper to convert From<UciDataSnd> into Vec<UciDataPacketHal>. An
592 // example usage is for fragmentation in the Data Packet Tx flow.
fragment_data_msg_send(packet: UciDataSnd, max_payload_len: usize) -> Vec<UciDataPacketHal>593 pub fn fragment_data_msg_send(packet: UciDataSnd, max_payload_len: usize) -> Vec<UciDataPacketHal> {
594 let mut fragments = Vec::new();
595 let dpf = packet.get_data_packet_format().into();
596
597 // get payload by stripping the header.
598 let payload = packet.encode_to_bytes().unwrap().slice(UCI_DATA_SND_PACKET_HEADER_LEN..);
599 if payload.is_empty() {
600 fragments.push(
601 UciDataPacketHalBuilder {
602 group_id_or_data_packet_format: dpf,
603 packet_boundary_flag: PacketBoundaryFlag::Complete,
604 payload: None,
605 }
606 .build(),
607 );
608 } else {
609 let mut fragments_iter = payload.chunks(max_payload_len).peekable();
610 while let Some(fragment) = fragments_iter.next() {
611 // Set the last fragment complete if this is last fragment.
612 let pbf = if let Some(nxt_fragment) = fragments_iter.peek() {
613 PacketBoundaryFlag::NotComplete
614 } else {
615 PacketBoundaryFlag::Complete
616 };
617 fragments.push(
618 UciDataPacketHalBuilder {
619 group_id_or_data_packet_format: dpf,
620 packet_boundary_flag: pbf,
621 payload: Some(Bytes::from(fragment.to_owned())),
622 }
623 .build(),
624 );
625 }
626 }
627 fragments
628 }
629
630 #[derive(Default, Debug)]
631 pub struct PacketDefrager {
632 // Cache to store incoming fragmented packets in the middle of reassembly.
633 // Will be empty if there is no reassembly in progress.
634 // TODO(b/261762781): Prefer this to be UciControlPacketHal
635 control_fragment_cache: Vec<UciPacketHal>,
636 // TODO(b/261762781): Prefer this to be UciDataPacketHal
637 data_fragment_cache: Vec<UciPacketHal>,
638 // Raw packet payload bytes cache
639 raw_fragment_cache: Vec<u8>,
640 }
641
642 pub enum UciDefragPacket {
643 Control(UciControlPacket),
644 Data(UciDataPacket),
645 Raw(Result<(), DecodeError>, RawUciControlPacket),
646 }
647
648 impl PacketDefrager {
defragment_packet( &mut self, msg: &[u8], last_raw_cmd: Option<RawUciControlPacket>, ) -> Option<UciDefragPacket>649 pub fn defragment_packet(
650 &mut self,
651 msg: &[u8],
652 last_raw_cmd: Option<RawUciControlPacket>,
653 ) -> Option<UciDefragPacket> {
654 if let Some(raw_cmd) = last_raw_cmd {
655 let mt_u8 = get_mt_from_uci_packet(msg);
656 match MessageType::try_from(u8::from(mt_u8)) {
657 Ok(mt) => match mt {
658 // Parse only a UCI response packet as a Raw packet.
659 MessageType::Response => {
660 return self.defragment_raw_uci_response_packet(msg, raw_cmd);
661 }
662 _ => { /* Fallthrough to de-frag as a normal UCI packet below */ }
663 },
664 Err(_) => {
665 error!("Rx packet from HAL has unrecognized MT={}", mt_u8);
666 return Some(UciDefragPacket::Raw(
667 Err(DecodeError::InvalidPacketError),
668 RawUciControlPacket { mt: mt_u8, gid: 0, oid: 0, payload: Vec::new() },
669 ));
670 }
671 };
672 }
673
674 let packet = UciPacketHal::parse(msg)
675 .or_else(|e| {
676 error!("Failed to parse packet: {:?}", e);
677 Err(e)
678 })
679 .ok()?;
680
681 let pbf = packet.get_packet_boundary_flag();
682
683 // TODO(b/261762781): The current implementation allows for the possibility that we receive
684 // interleaved Control/Data HAL packets, and so uses separate caches for them. In the
685 // future, if we determine that interleaving is not possible, this can be simplified.
686 if is_uci_control_packet(packet.get_message_type()) {
687 // Add the incoming fragment to the control packet cache.
688 self.control_fragment_cache.push(packet);
689 if pbf == PacketBoundaryFlag::NotComplete {
690 // Wait for remaining fragments.
691 return None;
692 }
693
694 // All fragments received, defragment the control packet.
695 match self.control_fragment_cache.drain(..).collect::<Vec<_>>().try_into() {
696 Ok(packet) => Some(UciDefragPacket::Control(packet)),
697 Err(e) => {
698 error!("Failed to defragment control packet: {:?}", e);
699 None
700 }
701 }
702 } else {
703 // Add the incoming fragment to the data packet cache.
704 self.data_fragment_cache.push(packet);
705 if pbf == PacketBoundaryFlag::NotComplete {
706 // Wait for remaining fragments.
707 return None;
708 }
709
710 // All fragments received, defragment the data packet.
711 match self.data_fragment_cache.drain(..).collect::<Vec<_>>().try_into() {
712 Ok(packet) => Some(UciDefragPacket::Data(packet)),
713 Err(e) => {
714 error!("Failed to defragment data packet: {:?}", e);
715 None
716 }
717 }
718 }
719 }
720
defragment_raw_uci_response_packet( &mut self, msg: &[u8], raw_cmd: RawUciControlPacket, ) -> Option<UciDefragPacket>721 fn defragment_raw_uci_response_packet(
722 &mut self,
723 msg: &[u8],
724 raw_cmd: RawUciControlPacket,
725 ) -> Option<UciDefragPacket> {
726 let mt_u8 = get_mt_from_uci_packet(msg);
727 let pbf = get_pbf_from_uci_packet(msg);
728 let gid = get_gid_from_uci_control_packet(msg);
729 let oid = get_oid_from_uci_control_packet(msg);
730 if raw_cmd.is_same_signature_bytes(msg) {
731 // Store only the packet payload bytes (UCI header should not be stored).
732 self.raw_fragment_cache.extend_from_slice(&msg[UCI_PACKET_HAL_HEADER_LEN..]);
733
734 if pbf == u8::from(PacketBoundaryFlag::NotComplete) {
735 return None;
736 }
737
738 // All fragments received, defragment and return the Raw packet's payload bytes.
739 return Some(UciDefragPacket::Raw(
740 Ok(()),
741 RawUciControlPacket {
742 mt: mt_u8,
743 gid,
744 oid,
745 payload: self.raw_fragment_cache.drain(..).collect(),
746 },
747 ));
748 } else {
749 error!(
750 "Rx packet from HAL (MT={}, PBF={}, GID={}, OID={}) has non-matching\
751 RawCmd signature",
752 mt_u8, pbf, gid, oid
753 );
754 return Some(UciDefragPacket::Raw(
755 Err(DecodeError::InvalidPacketError),
756 RawUciControlPacket { mt: mt_u8, gid, oid, payload: Vec::new() },
757 ));
758 }
759 }
760 }
761
762 #[allow(dead_code)]
763 #[derive(Debug, Clone)]
764 pub struct ParsedDiagnosticNtfPacket {
765 session_token: u32,
766 sequence_number: u32,
767 frame_reports: Vec<ParsedFrameReport>,
768 }
769
770 #[allow(dead_code)]
771 #[derive(Debug, Clone)]
772 pub struct ParsedFrameReport {
773 uwb_msg_id: u8,
774 action: u8,
775 antenna_set: u8,
776 rssi: Vec<u8>,
777 aoa: Vec<AoaMeasurement>,
778 cir: Vec<CirValue>,
779 segment_metrics: Vec<SegmentMetricsValue>,
780 }
781
parse_diagnostics_ntf( evt: AndroidRangeDiagnosticsNtf, ) -> Result<ParsedDiagnosticNtfPacket, DecodeError>782 pub fn parse_diagnostics_ntf(
783 evt: AndroidRangeDiagnosticsNtf,
784 ) -> Result<ParsedDiagnosticNtfPacket, DecodeError> {
785 let session_token = evt.get_session_token();
786 let sequence_number = evt.get_sequence_number();
787 let mut parsed_frame_reports = Vec::new();
788 for report in evt.get_frame_reports() {
789 let mut rssi_vec = Vec::new();
790 let mut aoa_vec = Vec::new();
791 let mut cir_vec = Vec::new();
792 let mut segment_metrics_vec = Vec::new();
793 for tlv in &report.frame_report_tlvs {
794 match FrameReportTlvPacket::parse(
795 &[vec![tlv.t as u8, tlv.v.len() as u8, (tlv.v.len() >> 8) as u8], tlv.v.clone()]
796 .concat(),
797 ) {
798 Ok(pkt) => match pkt.specialize() {
799 FrameReportTlvPacketChild::Rssi(rssi) => {
800 rssi_vec.append(&mut rssi.get_rssi().clone())
801 }
802 FrameReportTlvPacketChild::Aoa(aoa) => {
803 aoa_vec.append(&mut aoa.get_aoa().clone())
804 }
805 FrameReportTlvPacketChild::Cir(cir) => {
806 cir_vec.append(&mut cir.get_cir_value().clone())
807 }
808 FrameReportTlvPacketChild::SegmentMetrics(sm) => {
809 segment_metrics_vec.append(&mut sm.get_segment_metrics().clone())
810 }
811 _ => return Err(DecodeError::InvalidPacketError),
812 },
813 Err(e) => {
814 error!("Failed to parse the packet {:?}", e);
815 return Err(DecodeError::InvalidPacketError);
816 }
817 }
818 }
819 parsed_frame_reports.push(ParsedFrameReport {
820 uwb_msg_id: report.uwb_msg_id,
821 action: report.action,
822 antenna_set: report.antenna_set,
823 rssi: rssi_vec,
824 aoa: aoa_vec,
825 cir: cir_vec,
826 segment_metrics: segment_metrics_vec,
827 });
828 }
829 Ok(ParsedDiagnosticNtfPacket {
830 session_token,
831 sequence_number,
832 frame_reports: parsed_frame_reports,
833 })
834 }
835
836 #[derive(Debug, Clone, PartialEq)]
837 pub enum Controlees {
838 NoSessionKey(Vec<Controlee>),
839 ShortSessionKey(Vec<Controlee_V2_0_16_Byte_Version>),
840 LongSessionKey(Vec<Controlee_V2_0_32_Byte_Version>),
841 }
842
843 // TODO(ziyiw): Replace these functions after making uwb_uci_packets::Controlee::write_to() public.
write_controlee(controlee: &Controlee) -> BytesMut844 pub fn write_controlee(controlee: &Controlee) -> BytesMut {
845 let mut buffer = BytesMut::new();
846 buffer.extend_from_slice(&controlee.short_address);
847 let subsession_id = controlee.subsession_id;
848 buffer.extend_from_slice(&subsession_id.to_le_bytes()[0..4]);
849 buffer
850 }
851
write_controlee_2_0_16byte(controlee: &Controlee_V2_0_16_Byte_Version) -> BytesMut852 pub fn write_controlee_2_0_16byte(controlee: &Controlee_V2_0_16_Byte_Version) -> BytesMut {
853 let mut buffer = BytesMut::new();
854 buffer.extend_from_slice(&controlee.short_address);
855 let subsession_id = controlee.subsession_id;
856 buffer.extend_from_slice(&subsession_id.to_le_bytes()[0..4]);
857 buffer.extend_from_slice(&controlee.subsession_key);
858 buffer
859 }
860
write_controlee_2_0_32byte(controlee: &Controlee_V2_0_32_Byte_Version) -> BytesMut861 pub fn write_controlee_2_0_32byte(controlee: &Controlee_V2_0_32_Byte_Version) -> BytesMut {
862 let mut buffer = BytesMut::new();
863 buffer.extend_from_slice(&controlee.short_address);
864 let subsession_id = controlee.subsession_id;
865 buffer.extend_from_slice(&subsession_id.to_le_bytes()[0..4]);
866 buffer.extend_from_slice(&controlee.subsession_key);
867 buffer
868 }
869
870 /// Generate the SessionUpdateControllerMulticastListCmd packet.
871 ///
872 /// This function can build the packet with/without message control, which
873 /// is indicated by action parameter.
build_session_update_controller_multicast_list_cmd( session_token: u32, action: UpdateMulticastListAction, controlees: Controlees, ) -> Result<SessionUpdateControllerMulticastListCmd, DecodeError>874 pub fn build_session_update_controller_multicast_list_cmd(
875 session_token: u32,
876 action: UpdateMulticastListAction,
877 controlees: Controlees,
878 ) -> Result<SessionUpdateControllerMulticastListCmd, DecodeError> {
879 let mut controlees_buf = BytesMut::new();
880 match controlees {
881 Controlees::NoSessionKey(controlee_v1) => {
882 controlees_buf.extend_from_slice(&(controlee_v1.len() as u8).to_le_bytes());
883 for controlee in controlee_v1 {
884 controlees_buf.extend_from_slice(&write_controlee(&controlee));
885 }
886 }
887 Controlees::ShortSessionKey(controlee_v2)
888 if action == UpdateMulticastListAction::AddControleeWithShortSubSessionKey =>
889 {
890 controlees_buf.extend_from_slice(&(controlee_v2.len() as u8).to_le_bytes());
891 for controlee in controlee_v2 {
892 controlees_buf.extend_from_slice(&write_controlee_2_0_16byte(&controlee));
893 }
894 }
895 Controlees::LongSessionKey(controlee_v2)
896 if action == UpdateMulticastListAction::AddControleeWithLongSubSessionKey =>
897 {
898 controlees_buf.extend_from_slice(&(controlee_v2.len() as u8).to_le_bytes());
899 for controlee in controlee_v2 {
900 controlees_buf.extend_from_slice(&write_controlee_2_0_32byte(&controlee));
901 }
902 }
903 _ => return Err(DecodeError::InvalidPacketError),
904 }
905 Ok(SessionUpdateControllerMulticastListCmdBuilder {
906 session_token,
907 action,
908 payload: Some(controlees_buf.freeze()),
909 }
910 .build())
911 }
912
913 /// building Data transfer phase config command
build_data_transfer_phase_config_cmd( session_token: u32, dtpcm_repetition: u8, data_transfer_control: u8, dtpml_size: u8, mac_address: Vec<u8>, slot_bitmap: Vec<u8>, ) -> Result<SessionDataTransferPhaseConfigCmd, DecodeError>914 pub fn build_data_transfer_phase_config_cmd(
915 session_token: u32,
916 dtpcm_repetition: u8,
917 data_transfer_control: u8,
918 dtpml_size: u8,
919 mac_address: Vec<u8>,
920 slot_bitmap: Vec<u8>,
921 ) -> Result<SessionDataTransferPhaseConfigCmd, DecodeError> {
922 let mut dtpml_buffer = BytesMut::new();
923
924 //calculate mac address mode from data transfer control
925 let mac_address_mode = data_transfer_control & 0x01;
926
927 // Calculate mac address size based on address mode
928 let mac_address_size = match mac_address_mode {
929 SHORT_ADDRESS => 2,
930 EXTENDED_ADDRESS => 8,
931 _ => return Err(DecodeError::InvalidPacketError),
932 };
933
934 // Calculate slot bitmap size from data transfer control
935 let slot_bitmap_size = 1 << ((data_transfer_control & 0x0F) >> 1);
936
937 // Prepare segmented vectors for mac_address
938 let mac_address_vec: Vec<_> =
939 mac_address.chunks(mac_address_size).map(|chunk| chunk.to_owned()).collect();
940
941 // Prepare segmented vectors for slot_bitmap
942 let slot_bitmap_vec: Vec<_> =
943 slot_bitmap.chunks(slot_bitmap_size).map(|chunk| chunk.to_owned()).collect();
944
945 // Validate sizes of mac_address and slot_bitmap
946 if slot_bitmap_vec.len() != dtpml_size.into() || mac_address_vec.len() != dtpml_size.into() {
947 return Err(DecodeError::InvalidPacketError);
948 }
949
950 // Combine segmented vectors into dtpml_buffer
951 for (elem1, elem2) in mac_address_vec.into_iter().zip(slot_bitmap_vec.into_iter()) {
952 dtpml_buffer.extend_from_slice(&elem1);
953 dtpml_buffer.extend_from_slice(&elem2);
954 }
955
956 Ok(SessionDataTransferPhaseConfigCmdBuilder {
957 session_token,
958 dtpcm_repetition,
959 data_transfer_control,
960 dtpml_size,
961 payload: Some(dtpml_buffer.freeze()),
962 }
963 .build())
964 }
965
966 impl Drop for AppConfigTlv {
drop(&mut self)967 fn drop(&mut self) {
968 if self.cfg_id == AppConfigTlvType::VendorId || self.cfg_id == AppConfigTlvType::StaticStsIv
969 {
970 self.v.zeroize();
971 }
972 }
973 }
974
975 #[derive(Debug, Clone, PartialEq)]
976 pub enum PhaseList {
977 ShortMacAddress(Vec<PhaseListShortMacAddress>),
978 ExtendedMacAddress(Vec<PhaseListExtendedMacAddress>),
979 }
980
981 /// Generate the SessionSetHybridControllerConfig packet.
build_session_set_hybrid_controller_config_cmd( session_token: u32, message_control: u8, number_of_phases: u8, update_time: [u8; 8], phase_list: PhaseList, ) -> Result<SessionSetHybridControllerConfigCmd, DecodeError>982 pub fn build_session_set_hybrid_controller_config_cmd(
983 session_token: u32,
984 message_control: u8,
985 number_of_phases: u8,
986 update_time: [u8; 8],
987 phase_list: PhaseList,
988 ) -> Result<SessionSetHybridControllerConfigCmd, DecodeError> {
989 let mut phase_list_buffer = BytesMut::new();
990 match phase_list {
991 PhaseList::ShortMacAddress(phaseListShortMacAddressVec) => {
992 for phaseListShortMacAddress in phaseListShortMacAddressVec {
993 phase_list_buffer.extend_from_slice(
994 &(phaseListShortMacAddress.session_token.to_le_bytes()[0..4]),
995 );
996 phase_list_buffer.extend_from_slice(
997 &(phaseListShortMacAddress.start_slot_index.to_le_bytes()[0..2]),
998 );
999 phase_list_buffer.extend_from_slice(
1000 &(phaseListShortMacAddress.end_slot_index.to_le_bytes()[0..2]),
1001 );
1002 phase_list_buffer.extend_from_slice(std::slice::from_ref(
1003 &phaseListShortMacAddress.phase_participation,
1004 ));
1005 phase_list_buffer.extend_from_slice(&phaseListShortMacAddress.mac_address);
1006 }
1007 }
1008 PhaseList::ExtendedMacAddress(phaseListExtendedMacAddressVec) => {
1009 for phaseListExtendedMacAddress in phaseListExtendedMacAddressVec {
1010 phase_list_buffer.extend_from_slice(
1011 &(phaseListExtendedMacAddress.session_token.to_le_bytes()[0..4]),
1012 );
1013 phase_list_buffer.extend_from_slice(
1014 &(phaseListExtendedMacAddress.start_slot_index.to_le_bytes()[0..2]),
1015 );
1016 phase_list_buffer.extend_from_slice(
1017 &(phaseListExtendedMacAddress.end_slot_index.to_le_bytes()[0..2]),
1018 );
1019 phase_list_buffer.extend_from_slice(std::slice::from_ref(
1020 &phaseListExtendedMacAddress.phase_participation,
1021 ));
1022 phase_list_buffer.extend_from_slice(&phaseListExtendedMacAddress.mac_address);
1023 }
1024 }
1025 _ => return Err(DecodeError::InvalidPacketError),
1026 }
1027 Ok(SessionSetHybridControllerConfigCmdBuilder {
1028 session_token,
1029 message_control,
1030 number_of_phases,
1031 update_time,
1032 payload: Some(phase_list_buffer.freeze()),
1033 }
1034 .build())
1035 }
1036
1037 // Radar data 'bits per sample' field isn't a raw value, instead it's an enum
1038 // that maps to the raw value. We need this mapping to get the max sample size
1039 // length.
radar_bytes_per_sample_value(bps: BitsPerSample) -> u81040 pub fn radar_bytes_per_sample_value(bps: BitsPerSample) -> u8 {
1041 match bps {
1042 BitsPerSample::Value32 => 4,
1043 BitsPerSample::Value48 => 6,
1044 BitsPerSample::Value64 => 8,
1045 }
1046 }
1047
1048 #[cfg(test)]
1049 mod tests {
1050 use super::*;
1051
1052 #[test]
test_parse_diagnostics_ntf()1053 fn test_parse_diagnostics_ntf() {
1054 let rssi_vec = vec![0x01, 0x02, 0x03];
1055 let rssi = RssiBuilder { rssi: rssi_vec.clone() }.build();
1056 let aoa_1 = AoaMeasurement { tdoa: 1, pdoa: 2, aoa: 3, fom: 4, t: 1 };
1057 let aoa_2 = AoaMeasurement { tdoa: 5, pdoa: 6, aoa: 7, fom: 8, t: 2 };
1058 let aoa = AoaBuilder { aoa: vec![aoa_1.clone(), aoa_2.clone()] }.build();
1059 let cir_vec = vec![CirValue {
1060 first_path_index: 1,
1061 first_path_snr: 2,
1062 first_path_ns: 3,
1063 peak_path_index: 4,
1064 peak_path_snr: 5,
1065 peak_path_ns: 6,
1066 first_path_sample_offset: 7,
1067 samples_number: 2,
1068 sample_window: vec![0, 1, 2, 3],
1069 }];
1070 let cir = CirBuilder { cir_value: cir_vec.clone() }.build();
1071 let segment_metrics_vec = vec![SegmentMetricsValue {
1072 receiver: 1,
1073 rf_noise_floor: 2,
1074 segment_rsl: 3,
1075 first_path_index: 4,
1076 first_path_rsl: 5,
1077 first_path_time_ns: 6,
1078 peak_path_index: 7,
1079 peak_path_rsl: 8,
1080 peak_path_time_ns: 9,
1081 }];
1082 let segment_metrics =
1083 SegmentMetricsBuilder { segment_metrics: segment_metrics_vec.clone() }.build();
1084 let mut frame_reports = Vec::new();
1085 let tlvs = vec![
1086 FrameReportTlv { t: rssi.get_t(), v: rssi.get_rssi().to_vec() },
1087 FrameReportTlv { t: aoa.get_t(), v: aoa.encode_to_vec().unwrap()[3..].to_vec() },
1088 FrameReportTlv { t: cir.get_t(), v: cir.encode_to_vec().unwrap()[3..].to_vec() },
1089 FrameReportTlv {
1090 t: segment_metrics.get_t(),
1091 v: segment_metrics.encode_to_vec().unwrap()[3..].to_vec(),
1092 },
1093 ];
1094 let frame_report =
1095 FrameReport { uwb_msg_id: 1, action: 1, antenna_set: 1, frame_report_tlvs: tlvs };
1096 frame_reports.push(frame_report);
1097 let packet = AndroidRangeDiagnosticsNtfBuilder {
1098 session_token: 1,
1099 sequence_number: 1,
1100 frame_reports,
1101 }
1102 .build();
1103 let mut parsed_packet = parse_diagnostics_ntf(packet).unwrap();
1104 let parsed_frame_report = parsed_packet.frame_reports.pop().unwrap();
1105 assert_eq!(rssi_vec, parsed_frame_report.rssi);
1106 assert_eq!(aoa_1, parsed_frame_report.aoa[0]);
1107 assert_eq!(aoa_2, parsed_frame_report.aoa[1]);
1108 assert_eq!(cir_vec, parsed_frame_report.cir);
1109 assert_eq!(segment_metrics_vec, parsed_frame_report.segment_metrics);
1110 }
1111
1112 #[test]
test_write_controlee()1113 fn test_write_controlee() {
1114 let short_address: [u8; 2] = [2, 3];
1115 let controlee: Controlee = Controlee { short_address, subsession_id: 3 };
1116 let bytes = write_controlee(&controlee);
1117 let parsed_controlee = Controlee::parse(&bytes).unwrap();
1118 assert_eq!(controlee, parsed_controlee);
1119 }
1120
1121 #[test]
test_build_multicast_update_packet()1122 fn test_build_multicast_update_packet() {
1123 let short_address: [u8; 2] = [0x12, 0x34];
1124 let controlee = Controlee { short_address, subsession_id: 0x1324_3546 };
1125 let packet: UciControlPacket = build_session_update_controller_multicast_list_cmd(
1126 0x1425_3647,
1127 UpdateMulticastListAction::AddControlee,
1128 Controlees::NoSessionKey(vec![controlee; 1]),
1129 )
1130 .unwrap()
1131 .into();
1132 let packet_fragments: Vec<UciControlPacketHal> = packet.into();
1133 let uci_packet = packet_fragments[0].encode_to_vec();
1134 assert_eq!(
1135 uci_packet,
1136 Ok(vec![
1137 0x21, 0x07, 0x00, 0x0c, // 2(packet info), RFU, payload length(12)
1138 0x47, 0x36, 0x25, 0x14, // 4(session id (LE))
1139 0x00, 0x01, 0x12, 0x34, // action, # controlee, 2(short address (LE))
1140 0x46, 0x35, 0x24, 0x13, // 4(subsession id (LE))
1141 ])
1142 );
1143 }
1144
1145 #[test]
test_build_multicast_update_packet_v2_short_session_key()1146 fn test_build_multicast_update_packet_v2_short_session_key() {
1147 let short_address: [u8; 2] = [0x12, 0x34];
1148 let controlee = Controlee_V2_0_16_Byte_Version {
1149 short_address,
1150 subsession_id: 0x1324_3546,
1151 subsession_key: [
1152 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90, 0xab,
1153 0xcd, 0xef,
1154 ],
1155 };
1156 let packet: UciControlPacket = build_session_update_controller_multicast_list_cmd(
1157 0x1425_3647,
1158 UpdateMulticastListAction::AddControleeWithShortSubSessionKey,
1159 Controlees::ShortSessionKey(vec![controlee; 1]),
1160 )
1161 .unwrap()
1162 .into();
1163 let packet_fragments: Vec<UciControlPacketHal> = packet.into();
1164 let uci_packet = packet_fragments[0].encode_to_vec();
1165 assert_eq!(
1166 uci_packet,
1167 Ok(vec![
1168 0x21, 0x07, 0x00, 0x1c, // 2(packet info), RFU, payload length(28)
1169 0x47, 0x36, 0x25, 0x14, // 4(session id (LE))
1170 0x02, 0x01, 0x12, 0x34, // action, # controlee, 2(short address (LE))
1171 0x46, 0x35, 0x24, 0x13, // 4(subsession id (LE))
1172 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90, 0xab,
1173 0xcd, 0xef, // 16(subsession key(LE))
1174 ])
1175 );
1176 }
1177
1178 #[test]
test_build_multicast_update_packet_v2_long_session_key()1179 fn test_build_multicast_update_packet_v2_long_session_key() {
1180 let short_address: [u8; 2] = [0x12, 0x34];
1181 let controlee = Controlee_V2_0_32_Byte_Version {
1182 short_address,
1183 subsession_id: 0x1324_3546,
1184 subsession_key: [
1185 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90, 0xab,
1186 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78,
1187 0x90, 0xab, 0xcd, 0xef,
1188 ],
1189 };
1190 let packet: UciControlPacket = build_session_update_controller_multicast_list_cmd(
1191 0x1425_3647,
1192 UpdateMulticastListAction::AddControleeWithLongSubSessionKey,
1193 Controlees::LongSessionKey(vec![controlee; 1]),
1194 )
1195 .unwrap()
1196 .into();
1197 let packet_fragments: Vec<UciControlPacketHal> = packet.into();
1198 let uci_packet = packet_fragments[0].encode_to_vec();
1199 assert_eq!(
1200 uci_packet,
1201 Ok(vec![
1202 0x21, 0x07, 0x00, 0x2c, // 2(packet info), RFU, payload length(44)
1203 0x47, 0x36, 0x25, 0x14, // 4(session id (LE))
1204 0x03, 0x01, 0x12, 0x34, // action, # controlee, 2(short address (LE))
1205 0x46, 0x35, 0x24, 0x13, // 4(subsession id (LE))
1206 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90, 0xab,
1207 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78,
1208 0x90, 0xab, 0xcd, 0xef, // 32(subsession key(LE))
1209 ])
1210 );
1211 }
1212
1213 #[test]
test_to_raw_payload()1214 fn test_to_raw_payload() {
1215 let payload = vec![0x11, 0x22, 0x33];
1216 let payload_clone = payload.clone();
1217 let packet = UciControlPacketBuilder {
1218 group_id: GroupId::Test,
1219 message_type: MessageType::Response,
1220 opcode: 0x5,
1221 payload: Some(payload_clone.into()),
1222 }
1223 .build();
1224
1225 assert_eq!(payload, packet.to_raw_payload());
1226 }
1227
1228 #[test]
test_to_raw_payload_empty()1229 fn test_to_raw_payload_empty() {
1230 let payload: Vec<u8> = vec![];
1231 let packet = UciControlPacketBuilder {
1232 group_id: GroupId::Test,
1233 message_type: MessageType::Response,
1234 opcode: 0x5,
1235 payload: None,
1236 }
1237 .build();
1238
1239 assert_eq!(payload, packet.to_raw_payload());
1240 }
1241
1242 #[cfg(test)]
1243 mod tests {
1244 use crate::{extract_u16, extract_u32, extract_u64, extract_u8, extract_vec};
1245 #[test]
test_extract_func()1246 fn test_extract_func() {
1247 let bytes = [0x1, 0x3, 0x5, 0x7, 0x9, 0x2, 0x4, 0x05, 0x07, 0x09, 0x0a];
1248 let mut ptr = 0;
1249
1250 let u8_val = extract_u8(&bytes, &mut ptr, 1);
1251 assert_eq!(u8_val, Some(0x1));
1252 assert_eq!(ptr, 1);
1253
1254 let u16_val = extract_u16(&bytes, &mut ptr, 2);
1255 assert_eq!(u16_val, Some(0x0503));
1256 assert_eq!(ptr, 3);
1257
1258 let u32_val = extract_u32(&bytes, &mut ptr, 3);
1259 assert_eq!(u32_val, Some(0x020907));
1260 assert_eq!(ptr, 6);
1261
1262 let u64_val = extract_u64(&bytes, &mut ptr, 5);
1263 assert_eq!(u64_val, Some(0x0a09070504));
1264 assert_eq!(ptr, 11);
1265
1266 let vec = extract_vec(&bytes, &mut ptr, 3);
1267 assert_eq!(vec, None);
1268 assert_eq!(ptr, 11);
1269 }
1270 }
1271
1272 #[test]
test_short_dltdoa_ranging_measurement()1273 fn test_short_dltdoa_ranging_measurement() {
1274 let bytes = [
1275 // All Fields in Little Endian (LE)
1276 // First measurement
1277 0x0a, 0x01, 0x33, 0x05, // 2(Mac address), Status, Message Type
1278 0x53, 0x05, 0x02, 0x05, // 2(Message control), 2(Block Index)
1279 0x07, 0x09, 0x0a, 0x01, // Round Index, NLoS, 2(AoA Azimuth)
1280 0x02, 0x05, 0x07, 0x09, // AoA Azimuth FOM, 2(AoA Elevation), AoA Elevation FOM
1281 0x0a, 0x01, 0x02, 0x05, // RSSI, 3(Tx Timestamp..)
1282 0x07, 0x09, 0x0a, 0x01, // 4(Tx Timestamp..)
1283 0x02, 0x05, 0x07, 0x09, // Tx Timestamp, 3(Rx Timestamp..)
1284 0x05, 0x07, 0x09, 0x0a, // 2(Rx Timestamp), 2(Anchor Cfo)
1285 0x01, 0x02, 0x05, 0x07, // 2(Cfo), 2(Initiator Reply Time..)
1286 0x09, 0x05, 0x07, 0x09, // 2(Initiator Reply Time), 2(Responder Reply Time..)
1287 0x0a, 0x01, 0x02, 0x05, // 2(Responder Reply Time), 2(Initiator-Responder ToF)
1288 0x07, 0x09, 0x07, 0x09, // 4(Anchor Location..)
1289 0x05, 0x07, 0x09, 0x0a, // 4(Anchor Location..)
1290 0x01, 0x02, 0x05, 0x07, // 2(Anchor Location..), 2(Active Ranging Rounds..)
1291 0x09, 0x0a, 0x01, 0x02, // 4(Active Ranging Rounds..)
1292 0x05, 0x07, 0x09, 0x05, // 4(Active Ranging Rounds)
1293 // Second measurement
1294 0x0a, 0x01, 0x33, 0x05, // 2(Mac address), Status, Message Type
1295 0x33, 0x05, 0x02, 0x05, // 2(Message control), 2(Block Index)
1296 0x07, 0x09, 0x0a, 0x01, // Round Index, NLoS, 2(AoA Azimuth)
1297 0x02, 0x05, 0x07, 0x09, // AoA Azimuth FOM, 2(AoA Elevation), AoA Elevation FOM
1298 0x0a, 0x01, 0x02, 0x05, // RSSI, 3(Tx Timestamp..)
1299 0x07, 0x09, 0x0a, 0x01, // 4(Tx Timestamp..)
1300 0x02, 0x05, 0x07, 0x09, // Tx Timestamp, 3(Rx Timestamp..)
1301 0x05, 0x07, 0x09, 0x0a, // 2(Rx Timestamp), 2(Anchor Cfo)
1302 0x01, 0x02, 0x05, 0x07, // 2(Cfo), 2(Initiator Reply Time..)
1303 0x09, 0x05, 0x07, 0x09, // 2(Initiator Reply Time), 2(Responder Reply Time..)
1304 0x0a, 0x01, 0x02, 0x05, // 2(Responder Reply Time), 2(Initiator-Responder ToF)
1305 0x07, 0x09, 0x07, 0x09, // 4(Anchor Location..)
1306 0x05, 0x07, 0x09, 0x0a, // 4(Anchor Location..)
1307 0x01, 0x02, 0x01, 0x02, // 4(Anchor Location)
1308 0x05, 0x07, 0x09, 0x0a, // 4(Active Ranging Rounds..)
1309 0x01, 0x02, 0x05, 0x07, // 4(Active Ranging Rounds..)
1310 0x09, 0x05, // 2(Active Ranging Rounds)
1311 ];
1312
1313 let measurements = ShortAddressDlTdoaRangingMeasurement::parse(&bytes, 2).unwrap();
1314 assert_eq!(measurements.len(), 2);
1315 let measurement_1 = &measurements[0].measurement;
1316 let mac_address_1 = &measurements[0].mac_address;
1317 assert_eq!(*mac_address_1, 0x010a);
1318 assert_eq!(measurement_1.status, 0x33);
1319 assert_eq!(measurement_1.message_type, 0x05);
1320 assert_eq!(measurement_1.message_control, 0x0553);
1321 assert_eq!(measurement_1.block_index, 0x0502);
1322 assert_eq!(measurement_1.round_index, 0x07);
1323 assert_eq!(measurement_1.nlos, 0x09);
1324 assert_eq!(measurement_1.aoa_azimuth, 0x010a);
1325 assert_eq!(measurement_1.aoa_azimuth_fom, 0x02);
1326 assert_eq!(measurement_1.aoa_elevation, 0x0705);
1327 assert_eq!(measurement_1.aoa_elevation_fom, 0x09);
1328 assert_eq!(measurement_1.rssi, 0x0a);
1329 assert_eq!(measurement_1.tx_timestamp, 0x02010a0907050201);
1330 assert_eq!(measurement_1.rx_timestamp, 0x0705090705);
1331 assert_eq!(measurement_1.anchor_cfo, 0x0a09);
1332 assert_eq!(measurement_1.cfo, 0x0201);
1333 assert_eq!(measurement_1.initiator_reply_time, 0x05090705);
1334 assert_eq!(measurement_1.responder_reply_time, 0x010a0907);
1335 assert_eq!(measurement_1.initiator_responder_tof, 0x0502);
1336 assert_eq!(
1337 measurement_1.dt_anchor_location,
1338 vec![0x07, 0x09, 0x07, 0x09, 0x05, 0x07, 0x09, 0x0a, 0x01, 0x02]
1339 );
1340 assert_eq!(
1341 measurement_1.ranging_rounds,
1342 vec![0x05, 0x07, 0x09, 0x0a, 0x01, 0x02, 0x05, 0x07, 0x09, 0x05,]
1343 );
1344
1345 let measurement_2 = &measurements[1].measurement;
1346 let mac_address_2 = &measurements[1].mac_address;
1347 assert_eq!(*mac_address_2, 0x010a);
1348 assert_eq!(measurement_2.status, 0x33);
1349 assert_eq!(measurement_2.message_type, 0x05);
1350 assert_eq!(measurement_2.message_control, 0x0533);
1351 assert_eq!(measurement_2.block_index, 0x0502);
1352 assert_eq!(measurement_2.round_index, 0x07);
1353 assert_eq!(measurement_2.nlos, 0x09);
1354 assert_eq!(measurement_2.aoa_azimuth, 0x010a);
1355 assert_eq!(measurement_2.aoa_azimuth_fom, 0x02);
1356 assert_eq!(measurement_2.aoa_elevation, 0x0705);
1357 assert_eq!(measurement_2.aoa_elevation_fom, 0x09);
1358 assert_eq!(measurement_2.rssi, 0x0a);
1359 assert_eq!(measurement_2.tx_timestamp, 0x02010a0907050201);
1360 assert_eq!(measurement_2.rx_timestamp, 0x0705090705);
1361 assert_eq!(measurement_2.anchor_cfo, 0x0a09);
1362 assert_eq!(measurement_2.cfo, 0x0201);
1363 assert_eq!(measurement_2.initiator_reply_time, 0x05090705);
1364 assert_eq!(measurement_2.responder_reply_time, 0x010a0907);
1365 assert_eq!(measurement_2.initiator_responder_tof, 0x0502);
1366 assert_eq!(
1367 measurement_2.dt_anchor_location,
1368 vec![0x07, 0x09, 0x07, 0x09, 0x05, 0x07, 0x09, 0x0a, 0x01, 0x02, 0x01, 0x02]
1369 );
1370 assert_eq!(
1371 measurement_2.ranging_rounds,
1372 vec![0x05, 0x07, 0x09, 0x0a, 0x01, 0x02, 0x05, 0x07, 0x09, 0x05,]
1373 );
1374 }
1375
1376 #[test]
test_extended_dltdoa_ranging_measurement()1377 fn test_extended_dltdoa_ranging_measurement() {
1378 let bytes = [
1379 // All Fields in Little Endian (LE)
1380 /* First measurement */
1381 0x0a, 0x01, 0x33, 0x05, // 4(Mac address..)
1382 0x33, 0x05, 0x02, 0x05, // 4(Mac address)
1383 0x07, 0x09, 0x0a, 0x01, // Status, Message Type, 2(Message control),
1384 0x02, 0x05, 0x07, 0x09, // 2(Block Index), Round Index, NLoS,
1385 0x0a, 0x01, 0x02, 0x05, // 2(AoA Azimuth), AoA Azimuth FOM, 1(AoA Elevation..)
1386 0x07, 0x09, 0x0a, // 1(AoA Elevation), AoA Elevation FOM, RSSI,
1387 0x01, 0x02, 0x05, 0x07, // 4(Tx Timestamp..)
1388 0x09, 0x05, 0x07, 0x09, // 4(Tx Timestamp),
1389 0x0a, 0x01, 0x02, 0x05, // 4(Rx Timestamp..)
1390 0x07, 0x09, 0x05, 0x07, // 4(Rx Timestamp)
1391 0x09, 0x0a, 0x01, 0x02, // 2(Anchor Cfo), 2(Cfo),
1392 0x05, 0x07, 0x09, 0x05, // 4(Initiator Reply Time)
1393 0x07, 0x09, 0x0a, 0x01, // 4(Responder Reply Time),
1394 0x02, 0x05, 0x02, 0x05, // 2(Initiator-Responder ToF), 2(Active Ranging Rounds)
1395 ];
1396
1397 let measurements = ExtendedAddressDlTdoaRangingMeasurement::parse(&bytes, 1).unwrap();
1398 assert_eq!(measurements.len(), 1);
1399 let measurement = &measurements[0].measurement;
1400 let mac_address = &measurements[0].mac_address;
1401 assert_eq!(*mac_address, 0x050205330533010a);
1402 assert_eq!(measurement.message_control, 0x010a);
1403 assert_eq!(measurement.block_index, 0x0502);
1404 assert_eq!(measurement.round_index, 0x07);
1405 assert_eq!(measurement.nlos, 0x09);
1406 assert_eq!(measurement.aoa_azimuth, 0x010a);
1407 assert_eq!(measurement.aoa_azimuth_fom, 0x02);
1408 assert_eq!(measurement.aoa_elevation, 0x0705);
1409 assert_eq!(measurement.aoa_elevation_fom, 0x09);
1410 assert_eq!(measurement.rssi, 0x0a);
1411 assert_eq!(measurement.tx_timestamp, 0x0907050907050201);
1412 assert_eq!(measurement.rx_timestamp, 0x070509070502010a);
1413 assert_eq!(measurement.anchor_cfo, 0x0a09);
1414 assert_eq!(measurement.cfo, 0x0201);
1415 assert_eq!(measurement.initiator_reply_time, 0x05090705);
1416 assert_eq!(measurement.responder_reply_time, 0x010a0907);
1417 assert_eq!(measurement.initiator_responder_tof, 0x0502);
1418 assert_eq!(measurement.dt_anchor_location, vec![]);
1419 assert_eq!(measurement.ranging_rounds, vec![0x02, 0x05]);
1420 }
1421
1422 #[test]
test_build_data_transfer_phase_config_cmd()1423 fn test_build_data_transfer_phase_config_cmd() {
1424 let packet: UciControlPacket =
1425 build_data_transfer_phase_config_cmd(0x1234_5678, 0x0, 0x2, 1, vec![0, 1], vec![2, 3])
1426 .unwrap()
1427 .into();
1428 let packet_fragments: Vec<UciControlPacketHal> = packet.into();
1429 let uci_packet = packet_fragments[0].encode_to_vec();
1430 assert_eq!(
1431 uci_packet,
1432 Ok(vec![
1433 0x21, 0x0e, 0x00, 0x0b, // 2(packet info), RFU, payload length(11)
1434 0x78, 0x56, 0x34, 0x12, // 4(session id (LE))
1435 0x00, 0x02, 0x01, // dtpcm_repetition, data_transfer_control, dtpml_size
1436 0x00, 0x01, 0x02, 0x03, // payload
1437 ])
1438 );
1439 }
1440
1441 #[test]
test_build_session_set_hybrid_controller_config_cmd_short_address()1442 fn test_build_session_set_hybrid_controller_config_cmd_short_address() {
1443 let phase_list_short_mac_address = PhaseListShortMacAddress {
1444 session_token: 0x1324_3546,
1445 start_slot_index: 0x1111,
1446 end_slot_index: 0x1121,
1447 phase_participation: 0x0,
1448 mac_address: [0x1, 0x2],
1449 };
1450 let packet: UciControlPacket = build_session_set_hybrid_controller_config_cmd(
1451 0x1234_5678,
1452 0x0,
1453 0x0,
1454 [1; 8],
1455 PhaseList::ShortMacAddress(vec![phase_list_short_mac_address]),
1456 )
1457 .unwrap()
1458 .into();
1459 let packet_fragments: Vec<UciControlPacketHal> = packet.into();
1460 let uci_packet = packet_fragments[0].encode_to_vec();
1461 assert_eq!(
1462 uci_packet,
1463 Ok(vec![
1464 0x21, 0x0c, 0x00, 0x19, // 2(packet info), RFU, payload length(25)
1465 0x78, 0x56, 0x34, 0x12, // 4(session id (LE))
1466 0x00, 0x00, // message_control, number_of_phases
1467 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // update_time
1468 0x46, 0x35, 0x24, 0x13, // session id (LE)
1469 0x11, 0x11, // start slot index (LE)
1470 0x21, 0x11, // end slot index (LE)
1471 0x00, // phase_participation
1472 0x01, 0x02, // mac address
1473 ])
1474 );
1475 }
1476
1477 #[test]
test_build_session_set_hybrid_controller_config_cmd_extended_address()1478 fn test_build_session_set_hybrid_controller_config_cmd_extended_address() {
1479 let phase_list_extended_mac_address = PhaseListExtendedMacAddress {
1480 session_token: 0x1324_3546,
1481 start_slot_index: 0x1111,
1482 end_slot_index: 0x1121,
1483 phase_participation: 0x0,
1484 mac_address: [0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8],
1485 };
1486 let packet: UciControlPacket = build_session_set_hybrid_controller_config_cmd(
1487 0x1234_5678,
1488 0x0,
1489 0x0,
1490 [1; 8],
1491 PhaseList::ExtendedMacAddress(vec![phase_list_extended_mac_address]),
1492 )
1493 .unwrap()
1494 .into();
1495 let packet_fragments: Vec<UciControlPacketHal> = packet.into();
1496 let uci_packet = packet_fragments[0].encode_to_vec();
1497 assert_eq!(
1498 uci_packet,
1499 Ok(vec![
1500 0x21, 0x0c, 0x00, 0x1f, // 2(packet info), RFU, payload length(31)
1501 0x78, 0x56, 0x34, 0x12, // 4(session id (LE))
1502 0x00, 0x00, // message_control, number_of_phases
1503 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // update_time
1504 0x46, 0x35, 0x24, 0x13, // session id (LE)
1505 0x11, 0x11, // start slot index (LE)
1506 0x21, 0x11, // end slot index (LE)
1507 0x00, // phase_participation
1508 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 // mac address
1509 ])
1510 );
1511 }
1512 }
1513