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