xref: /aosp_15_r20/external/uwb/src/rust/uwb_core/src/params/uci_packets.rs (revision e0df40009cb5d71e642272d38ba1bb7ffccfce41)
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 //! This module defines the parameters or responses of the UciManager's methods. Most of them are
16 //! re-exported from the uwb_uci_packets crate.
17 
18 use std::collections::{hash_map::RandomState, HashMap};
19 use std::iter::FromIterator;
20 
21 use num_derive::{FromPrimitive, ToPrimitive};
22 
23 // Re-export enums and structs from uwb_uci_packets.
24 pub use uwb_uci_packets::{
25     AppConfigStatus, AppConfigTlv as RawAppConfigTlv, AppConfigTlvType, BitsPerSample, CapTlv,
26     CapTlvType, Controlee, ControleePhaseList, ControleeStatusV1, ControleeStatusV2, Controlees,
27     CreditAvailability, DataRcvStatusCode, DataTransferNtfStatusCode,
28     DataTransferPhaseConfigUpdateStatusCode, DeviceConfigId, DeviceConfigStatus, DeviceConfigTlv,
29     DeviceState, ExtendedAddressDlTdoaRangingMeasurement, ExtendedAddressOwrAoaRangingMeasurement,
30     ExtendedAddressTwoWayRangingMeasurement, GroupId, MacAddressIndicator, MessageType,
31     MulticastUpdateStatusCode, PhaseList, PowerStats, RadarConfigStatus, RadarConfigTlv,
32     RadarConfigTlvType, RadarDataType, RangingMeasurementType, ReasonCode, ResetConfig,
33     RfTestConfigStatus, RfTestConfigTlv, RfTestConfigTlvType, SessionState, SessionType,
34     SessionUpdateControllerMulticastListNtfV1Payload,
35     SessionUpdateControllerMulticastListNtfV2Payload,
36     SessionUpdateControllerMulticastListRspV1Payload,
37     SessionUpdateControllerMulticastListRspV2Payload, ShortAddressDlTdoaRangingMeasurement,
38     ShortAddressOwrAoaRangingMeasurement, ShortAddressTwoWayRangingMeasurement, StatusCode,
39     UpdateMulticastListAction,
40 };
41 pub(crate) use uwb_uci_packets::{UciControlPacket, UciDataPacket, UciDataPacketHal};
42 
43 use crate::error::Error;
44 
45 /// The type of the session identifier.
46 pub type SessionId = u32;
47 /// The type of the sub-session identifier.
48 pub type SubSessionId = u32;
49 /// The type of the session handle.
50 pub type SessionHandle = u32;
51 /// Generic type used to represent either a session id or session handle.
52 pub type SessionToken = u32;
53 
54 /// Wrap the original AppConfigTlv type to redact the PII fields when logging.
55 #[derive(Clone, PartialEq)]
56 pub struct AppConfigTlv {
57     tlv: RawAppConfigTlv,
58 }
59 
60 /// Controlee Status Enum compatible with different Fira version.
61 pub enum ControleeStatusList {
62     /// Controlee status defined in Fira 1.x.
63     V1(Vec<ControleeStatusV1>),
64     /// Controlee status defined in Fira 2.0.
65     V2(Vec<ControleeStatusV2>),
66 }
67 
68 /// UCI major version
69 #[derive(FromPrimitive, ToPrimitive, PartialEq, Clone)]
70 #[repr(u8)]
71 pub enum UCIMajorVersion {
72     /// Version 1.x
73     V1 = 1,
74     /// Version 2.0
75     V2 = 2,
76 }
77 
78 impl std::fmt::Debug for AppConfigTlv {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error>79     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
80         static REDACTED_STR: &str = "redacted";
81 
82         let mut ds = f.debug_struct("AppConfigTlv");
83         ds.field("cfg_id", &self.tlv.cfg_id);
84         if self.tlv.cfg_id == AppConfigTlvType::VendorId
85             || self.tlv.cfg_id == AppConfigTlvType::StaticStsIv
86         {
87             ds.field("v", &REDACTED_STR);
88         } else {
89             ds.field("v", &self.tlv.v);
90         }
91         ds.finish()
92     }
93 }
94 
95 impl AppConfigTlv {
96     /// Create a wrapper of uwb_uci_packets::AppConfigTlv.
97     ///
98     /// The argument is the same as the uwb_uci_packets::AppConfigTlv's struct.
new(cfg_id: AppConfigTlvType, v: Vec<u8>) -> Self99     pub fn new(cfg_id: AppConfigTlvType, v: Vec<u8>) -> Self {
100         Self { tlv: RawAppConfigTlv { cfg_id, v } }
101     }
102 
103     /// Consumes the outter wrapper type, returning the wrapped uwb_uci_packets::AppConfigTlv.
into_inner(self) -> RawAppConfigTlv104     pub fn into_inner(self) -> RawAppConfigTlv {
105         self.tlv
106     }
107 }
108 
109 impl From<RawAppConfigTlv> for AppConfigTlv {
from(tlv: RawAppConfigTlv) -> Self110     fn from(tlv: RawAppConfigTlv) -> Self {
111         Self { tlv }
112     }
113 }
114 
115 impl std::ops::Deref for AppConfigTlv {
116     type Target = RawAppConfigTlv;
deref(&self) -> &Self::Target117     fn deref(&self) -> &Self::Target {
118         &self.tlv
119     }
120 }
121 
122 impl std::ops::DerefMut for AppConfigTlv {
deref_mut(&mut self) -> &mut Self::Target123     fn deref_mut(&mut self) -> &mut Self::Target {
124         &mut self.tlv
125     }
126 }
127 
128 /// Compare if two AppConfigTlv array are equal. Convert the array to HashMap before comparing
129 /// because the order of TLV elements doesn't matter.
130 #[allow(dead_code)]
app_config_tlvs_eq(a: &[AppConfigTlv], b: &[AppConfigTlv]) -> bool131 pub fn app_config_tlvs_eq(a: &[AppConfigTlv], b: &[AppConfigTlv]) -> bool {
132     app_config_tlvs_to_map(a) == app_config_tlvs_to_map(b)
133 }
134 
app_config_tlvs_to_map( tlvs: &[AppConfigTlv], ) -> HashMap<AppConfigTlvType, &Vec<u8>, RandomState>135 fn app_config_tlvs_to_map(
136     tlvs: &[AppConfigTlv],
137 ) -> HashMap<AppConfigTlvType, &Vec<u8>, RandomState> {
138     HashMap::from_iter(tlvs.iter().map(|config| (config.cfg_id, &config.v)))
139 }
140 
141 /// Compare if two DeviceConfigTlv array are equal. Convert the array to HashMap before comparing
142 /// because the order of TLV elements doesn't matter.
143 #[allow(dead_code)]
device_config_tlvs_eq(a: &[DeviceConfigTlv], b: &[DeviceConfigTlv]) -> bool144 pub fn device_config_tlvs_eq(a: &[DeviceConfigTlv], b: &[DeviceConfigTlv]) -> bool {
145     device_config_tlvs_to_map(a) == device_config_tlvs_to_map(b)
146 }
147 
device_config_tlvs_to_map( tlvs: &[DeviceConfigTlv], ) -> HashMap<DeviceConfigId, &Vec<u8>, RandomState>148 fn device_config_tlvs_to_map(
149     tlvs: &[DeviceConfigTlv],
150 ) -> HashMap<DeviceConfigId, &Vec<u8>, RandomState> {
151     HashMap::from_iter(tlvs.iter().map(|config| (config.cfg_id, &config.v)))
152 }
153 
154 /// Compare if two RadarConfigTlv array are equal. Convert the array to HashMap before comparing
155 /// because the order of TLV elements doesn't matter.
156 #[allow(dead_code)]
radar_config_tlvs_eq(a: &[RadarConfigTlv], b: &[RadarConfigTlv]) -> bool157 pub fn radar_config_tlvs_eq(a: &[RadarConfigTlv], b: &[RadarConfigTlv]) -> bool {
158     radar_config_tlvs_to_map(a) == radar_config_tlvs_to_map(b)
159 }
160 
radar_config_tlvs_to_map( tlvs: &[RadarConfigTlv], ) -> HashMap<RadarConfigTlvType, &Vec<u8>, RandomState>161 fn radar_config_tlvs_to_map(
162     tlvs: &[RadarConfigTlv],
163 ) -> HashMap<RadarConfigTlvType, &Vec<u8>, RandomState> {
164     HashMap::from_iter(tlvs.iter().map(|config| (config.cfg_id, &config.v)))
165 }
166 
167 /// Compare if two RfTestConfigTlv array are equal. Convert the array to HashMap before comparing
168 /// because the order of TLV elements doesn't matter.
169 #[allow(dead_code)]
rf_test_config_tlvs_eq(a: &[RfTestConfigTlv], b: &[RfTestConfigTlv]) -> bool170 pub fn rf_test_config_tlvs_eq(a: &[RfTestConfigTlv], b: &[RfTestConfigTlv]) -> bool {
171     rf_test_config_tlvs_to_map(a) == rf_test_config_tlvs_to_map(b)
172 }
173 
rf_test_config_tlvs_to_map( tlvs: &[RfTestConfigTlv], ) -> HashMap<RfTestConfigTlvType, &Vec<u8>, RandomState>174 fn rf_test_config_tlvs_to_map(
175     tlvs: &[RfTestConfigTlv],
176 ) -> HashMap<RfTestConfigTlvType, &Vec<u8>, RandomState> {
177     HashMap::from_iter(tlvs.iter().map(|config| (config.cfg_id, &config.v)))
178 }
179 
180 /// The response of the UciManager::core_set_config() method.
181 #[derive(Debug, Clone, PartialEq)]
182 pub struct CoreSetConfigResponse {
183     /// The status code of the response.
184     pub status: StatusCode,
185     /// The status of each config TLV.
186     pub config_status: Vec<DeviceConfigStatus>,
187 }
188 
189 /// The response of the UciManager::session_set_app_config() method.
190 #[derive(Debug, Clone, PartialEq)]
191 pub struct SetAppConfigResponse {
192     /// The status code of the response.
193     pub status: StatusCode,
194     /// The status of each config TLV.
195     pub config_status: Vec<AppConfigStatus>,
196 }
197 
198 /// The response of the UciManager::android_set_radar_config() method.
199 #[derive(Debug, Clone, PartialEq)]
200 pub struct AndroidRadarConfigResponse {
201     /// The status code of the response.
202     pub status: StatusCode,
203     /// The status of each config TLV.
204     pub config_status: Vec<RadarConfigStatus>,
205 }
206 
207 /// The response from UciManager::(session_update_controller_multicast_list() method.
208 #[derive(Debug, Clone, PartialEq, Eq)]
209 pub struct SessionUpdateControllerMulticastResponse {
210     /// The status code of the response.
211     pub status: StatusCode,
212     /// Controlee Status
213     pub status_list: Vec<ControleeStatusV2>,
214 }
215 
216 /// The response from UciManager::session_update_dt_tag_ranging_rounds() method.
217 #[derive(Debug, Clone, PartialEq, Eq)]
218 pub struct SessionUpdateDtTagRangingRoundsResponse {
219     /// The status code of the response.
220     pub status: StatusCode,
221     /// Indexes of unsuccessful ranging rounds.
222     pub ranging_round_indexes: Vec<u8>,
223 }
224 
225 /// The response of the UciManager::android_set_rf_test_config() method.
226 #[derive(Debug, Clone, PartialEq)]
227 pub struct RfTestConfigResponse {
228     /// The status code of the response.
229     pub status: StatusCode,
230     /// The status of each config TLV.
231     pub config_status: Vec<RfTestConfigStatus>,
232 }
233 
234 /// The country code struct that contains 2 uppercase ASCII characters.
235 #[derive(Debug, Clone, PartialEq, Eq)]
236 pub struct CountryCode([u8; 2]);
237 
238 impl CountryCode {
239     const UNKNOWN_COUNTRY_CODE: &'static [u8] = "00".as_bytes();
240 
241     /// Create a CountryCode instance.
new(code: &[u8; 2]) -> Option<Self>242     pub fn new(code: &[u8; 2]) -> Option<Self> {
243         if code != CountryCode::UNKNOWN_COUNTRY_CODE
244             && !code.iter().all(|x| (*x as char).is_ascii_alphabetic())
245         {
246             None
247         } else {
248             Some(Self((*code).to_ascii_uppercase().try_into().ok()?))
249         }
250     }
251 }
252 
253 impl From<CountryCode> for [u8; 2] {
from(item: CountryCode) -> [u8; 2]254     fn from(item: CountryCode) -> [u8; 2] {
255         item.0
256     }
257 }
258 
259 impl TryFrom<String> for CountryCode {
260     type Error = Error;
try_from(item: String) -> Result<Self, Self::Error>261     fn try_from(item: String) -> Result<Self, Self::Error> {
262         let code = item.as_bytes().try_into().map_err(|_| Error::BadParameters)?;
263         Self::new(code).ok_or(Error::BadParameters)
264     }
265 }
266 
267 /// absolute time in UWBS Time domain(ms) when this configuration applies
268 #[derive(Debug, Clone, PartialEq, Copy)]
269 pub struct UpdateTime([u8; 8]);
270 
271 impl UpdateTime {
272     /// Create a UpdateTime instance.
new(update_time: &[u8; 8]) -> Option<Self>273     pub fn new(update_time: &[u8; 8]) -> Option<Self> {
274         Some(Self(*update_time))
275     }
276 }
277 
278 impl From<UpdateTime> for [u8; 8] {
from(item: UpdateTime) -> [u8; 8]279     fn from(item: UpdateTime) -> [u8; 8] {
280         item.0
281     }
282 }
283 
284 /// The response of the UciManager::core_get_device_info() method.
285 #[derive(Debug, Clone, PartialEq, Eq)]
286 pub struct GetDeviceInfoResponse {
287     /// Status
288     pub status: StatusCode,
289     /// The UCI version.
290     pub uci_version: u16,
291     /// The MAC version.
292     pub mac_version: u16,
293     /// The physical version.
294     pub phy_version: u16,
295     /// The UCI test version.
296     pub uci_test_version: u16,
297     /// The vendor spec info.
298     pub vendor_spec_info: Vec<u8>,
299 }
300 
301 /// The raw UCI message for the vendor commands.
302 #[derive(Debug, Clone, PartialEq, Eq)]
303 pub struct RawUciMessage {
304     /// The group id of the message.
305     pub gid: u32,
306     /// The opcode of the message.
307     pub oid: u32,
308     /// The payload of the message.
309     pub payload: Vec<u8>,
310 }
311 
312 impl From<UciControlPacket> for RawUciMessage {
from(packet: UciControlPacket) -> Self313     fn from(packet: UciControlPacket) -> Self {
314         Self {
315             gid: packet.get_group_id().into(),
316             oid: packet.get_opcode() as u32,
317             payload: packet.to_raw_payload(),
318         }
319     }
320 }
321 
322 #[cfg(test)]
323 mod tests {
324     use super::*;
325 
326     #[test]
test_redacted_app_config_tlv()327     fn test_redacted_app_config_tlv() {
328         // The value of VendorId and StaticStsIv should be redacted.
329         let tlv = AppConfigTlv::new(AppConfigTlvType::VendorId, vec![12, 34]);
330         let format_str = format!("{tlv:?}");
331         assert!(format_str.contains("v: \"redacted\""));
332 
333         let tlv = AppConfigTlv::new(AppConfigTlvType::StaticStsIv, vec![12, 34]);
334         let format_str = format!("{tlv:?}");
335         assert!(format_str.contains("v: \"redacted\""));
336 
337         // The value of DeviceType should be printed normally.
338         let tlv = AppConfigTlv::new(AppConfigTlvType::DeviceType, vec![12, 34]);
339         let format_str = format!("{tlv:?}");
340         assert_eq!(format_str, "AppConfigTlv { cfg_id: DeviceType, v: [12, 34] }");
341     }
342 
343     #[test]
test_country_code()344     fn test_country_code() {
345         let _country_code_ascii: CountryCode = String::from("US").try_into().unwrap();
346         let _country_code_unknown: CountryCode = String::from("00").try_into().unwrap();
347         let country_code_invalid_1: Result<CountryCode, Error> = String::from("0S").try_into();
348         country_code_invalid_1.unwrap_err();
349         let country_code_invalid_2: Result<CountryCode, Error> = String::from("ÀÈ").try_into();
350         country_code_invalid_2.unwrap_err();
351     }
352 
353     #[test]
test_rf_test_config_tlvs_eq()354     fn test_rf_test_config_tlvs_eq() {
355         let tlv1 = RfTestConfigTlv { cfg_id: RfTestConfigTlvType::NumPackets, v: vec![10, 20] };
356         let tlv2 = RfTestConfigTlv { cfg_id: RfTestConfigTlvType::TStart, v: vec![30, 40] };
357 
358         let array1 = vec![tlv1.clone(), tlv2.clone()];
359         let array2 = vec![tlv2.clone(), tlv1.clone()]; // Different order
360 
361         // Test that arrays with the same elements in different orders are equal.
362         assert!(rf_test_config_tlvs_eq(&array1, &array2));
363 
364         let tlv3 = RfTestConfigTlv {
365             cfg_id: RfTestConfigTlvType::TWin,
366             v: vec![70, 80], // Different value
367         };
368 
369         let array3 = vec![tlv1.clone(), tlv3.clone()];
370 
371         // Test that arrays with different elements are not equal.
372         assert!(!rf_test_config_tlvs_eq(&array1, &array3));
373     }
374 }
375