• 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 //! 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     ControllerPhaseList, CreditAvailability, DataRcvStatusCode, DataTransferNtfStatusCode,
28     DataTransferPhaseConfigUpdateStatusCode, DeviceConfigId, DeviceConfigStatus, DeviceConfigTlv,
29     DeviceState, ExtendedAddressDlTdoaRangingMeasurement, ExtendedAddressOwrAoaRangingMeasurement,
30     ExtendedAddressTwoWayRangingMeasurement, GroupId, MacAddressIndicator, MessageType,
31     MulticastUpdateStatusCode, PowerStats, RadarConfigStatus, RadarConfigTlv, RadarConfigTlvType,
32     RadarDataType, RangingMeasurementType, ReasonCode, ResetConfig, RfTestConfigStatus,
33     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, PartialOrd, Ord, Eq)]
70 #[repr(u8)]
71 pub enum UCIMajorVersion {
72     /// Version 1.x
73     V1 = 1,
74     /// Version 2.0
75     V2 = 2,
76     /// Version 3.0
77     V3 = 3,
78 }
79 
80 impl std::fmt::Debug for AppConfigTlv {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error>81     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
82         static REDACTED_STR: &str = "redacted";
83 
84         let mut ds = f.debug_struct("AppConfigTlv");
85         ds.field("cfg_id", &self.tlv.cfg_id);
86         if self.tlv.cfg_id == AppConfigTlvType::VendorId
87             || self.tlv.cfg_id == AppConfigTlvType::StaticStsIv
88         {
89             ds.field("v", &REDACTED_STR);
90         } else {
91             ds.field("v", &self.tlv.v);
92         }
93         ds.finish()
94     }
95 }
96 
97 impl AppConfigTlv {
98     /// Create a wrapper of uwb_uci_packets::AppConfigTlv.
99     ///
100     /// The argument is the same as the uwb_uci_packets::AppConfigTlv's struct.
new(cfg_id: AppConfigTlvType, v: Vec<u8>) -> Self101     pub fn new(cfg_id: AppConfigTlvType, v: Vec<u8>) -> Self {
102         Self { tlv: RawAppConfigTlv { cfg_id, v } }
103     }
104 
105     /// Consumes the outter wrapper type, returning the wrapped uwb_uci_packets::AppConfigTlv.
into_inner(self) -> RawAppConfigTlv106     pub fn into_inner(self) -> RawAppConfigTlv {
107         self.tlv
108     }
109 }
110 
111 impl From<RawAppConfigTlv> for AppConfigTlv {
from(tlv: RawAppConfigTlv) -> Self112     fn from(tlv: RawAppConfigTlv) -> Self {
113         Self { tlv }
114     }
115 }
116 
117 impl std::ops::Deref for AppConfigTlv {
118     type Target = RawAppConfigTlv;
deref(&self) -> &Self::Target119     fn deref(&self) -> &Self::Target {
120         &self.tlv
121     }
122 }
123 
124 impl std::ops::DerefMut for AppConfigTlv {
deref_mut(&mut self) -> &mut Self::Target125     fn deref_mut(&mut self) -> &mut Self::Target {
126         &mut self.tlv
127     }
128 }
129 
130 /// Compare if two AppConfigTlv array are equal. Convert the array to HashMap before comparing
131 /// because the order of TLV elements doesn't matter.
132 #[allow(dead_code)]
app_config_tlvs_eq(a: &[AppConfigTlv], b: &[AppConfigTlv]) -> bool133 pub fn app_config_tlvs_eq(a: &[AppConfigTlv], b: &[AppConfigTlv]) -> bool {
134     app_config_tlvs_to_map(a) == app_config_tlvs_to_map(b)
135 }
136 
app_config_tlvs_to_map( tlvs: &[AppConfigTlv], ) -> HashMap<AppConfigTlvType, &Vec<u8>, RandomState>137 fn app_config_tlvs_to_map(
138     tlvs: &[AppConfigTlv],
139 ) -> HashMap<AppConfigTlvType, &Vec<u8>, RandomState> {
140     HashMap::from_iter(tlvs.iter().map(|config| (config.cfg_id, &config.v)))
141 }
142 
143 /// Compare if two DeviceConfigTlv array are equal. Convert the array to HashMap before comparing
144 /// because the order of TLV elements doesn't matter.
145 #[allow(dead_code)]
device_config_tlvs_eq(a: &[DeviceConfigTlv], b: &[DeviceConfigTlv]) -> bool146 pub fn device_config_tlvs_eq(a: &[DeviceConfigTlv], b: &[DeviceConfigTlv]) -> bool {
147     device_config_tlvs_to_map(a) == device_config_tlvs_to_map(b)
148 }
149 
device_config_tlvs_to_map( tlvs: &[DeviceConfigTlv], ) -> HashMap<DeviceConfigId, &Vec<u8>, RandomState>150 fn device_config_tlvs_to_map(
151     tlvs: &[DeviceConfigTlv],
152 ) -> HashMap<DeviceConfigId, &Vec<u8>, RandomState> {
153     HashMap::from_iter(tlvs.iter().map(|config| (config.cfg_id, &config.v)))
154 }
155 
156 /// Compare if two RadarConfigTlv array are equal. Convert the array to HashMap before comparing
157 /// because the order of TLV elements doesn't matter.
158 #[allow(dead_code)]
radar_config_tlvs_eq(a: &[RadarConfigTlv], b: &[RadarConfigTlv]) -> bool159 pub fn radar_config_tlvs_eq(a: &[RadarConfigTlv], b: &[RadarConfigTlv]) -> bool {
160     radar_config_tlvs_to_map(a) == radar_config_tlvs_to_map(b)
161 }
162 
radar_config_tlvs_to_map( tlvs: &[RadarConfigTlv], ) -> HashMap<RadarConfigTlvType, &Vec<u8>, RandomState>163 fn radar_config_tlvs_to_map(
164     tlvs: &[RadarConfigTlv],
165 ) -> HashMap<RadarConfigTlvType, &Vec<u8>, RandomState> {
166     HashMap::from_iter(tlvs.iter().map(|config| (config.cfg_id, &config.v)))
167 }
168 
169 /// Compare if two RfTestConfigTlv array are equal. Convert the array to HashMap before comparing
170 /// because the order of TLV elements doesn't matter.
171 #[allow(dead_code)]
rf_test_config_tlvs_eq(a: &[RfTestConfigTlv], b: &[RfTestConfigTlv]) -> bool172 pub fn rf_test_config_tlvs_eq(a: &[RfTestConfigTlv], b: &[RfTestConfigTlv]) -> bool {
173     rf_test_config_tlvs_to_map(a) == rf_test_config_tlvs_to_map(b)
174 }
175 
rf_test_config_tlvs_to_map( tlvs: &[RfTestConfigTlv], ) -> HashMap<RfTestConfigTlvType, &Vec<u8>, RandomState>176 fn rf_test_config_tlvs_to_map(
177     tlvs: &[RfTestConfigTlv],
178 ) -> HashMap<RfTestConfigTlvType, &Vec<u8>, RandomState> {
179     HashMap::from_iter(tlvs.iter().map(|config| (config.cfg_id, &config.v)))
180 }
181 
182 /// The response of the UciManager::core_set_config() method.
183 #[derive(Debug, Clone, PartialEq)]
184 pub struct CoreSetConfigResponse {
185     /// The status code of the response.
186     pub status: StatusCode,
187     /// The status of each config TLV.
188     pub config_status: Vec<DeviceConfigStatus>,
189 }
190 
191 /// The response of the UciManager::session_set_app_config() method.
192 #[derive(Debug, Clone, PartialEq)]
193 pub struct SetAppConfigResponse {
194     /// The status code of the response.
195     pub status: StatusCode,
196     /// The status of each config TLV.
197     pub config_status: Vec<AppConfigStatus>,
198 }
199 
200 /// The response of the UciManager::android_set_radar_config() method.
201 #[derive(Debug, Clone, PartialEq)]
202 pub struct AndroidRadarConfigResponse {
203     /// The status code of the response.
204     pub status: StatusCode,
205     /// The status of each config TLV.
206     pub config_status: Vec<RadarConfigStatus>,
207 }
208 
209 /// The response from UciManager::(session_update_controller_multicast_list() method.
210 #[derive(Debug, Clone, PartialEq, Eq)]
211 pub struct SessionUpdateControllerMulticastResponse {
212     /// The status code of the response.
213     pub status: StatusCode,
214     /// Controlee Status
215     pub status_list: Vec<ControleeStatusV2>,
216 }
217 
218 /// The response from UciManager::session_update_dt_tag_ranging_rounds() method.
219 #[derive(Debug, Clone, PartialEq, Eq)]
220 pub struct SessionUpdateDtTagRangingRoundsResponse {
221     /// The status code of the response.
222     pub status: StatusCode,
223     /// Indexes of unsuccessful ranging rounds.
224     pub ranging_round_indexes: Vec<u8>,
225 }
226 
227 /// The response of the UciManager::android_set_rf_test_config() method.
228 #[derive(Debug, Clone, PartialEq)]
229 pub struct RfTestConfigResponse {
230     /// The status code of the response.
231     pub status: StatusCode,
232     /// The status of each config TLV.
233     pub config_status: Vec<RfTestConfigStatus>,
234 }
235 
236 /// The country code struct that contains 2 uppercase ASCII characters.
237 #[derive(Debug, Clone, PartialEq, Eq)]
238 pub struct CountryCode([u8; 2]);
239 
240 impl CountryCode {
241     const UNKNOWN_COUNTRY_CODE: &'static [u8] = "00".as_bytes();
242 
243     /// Create a CountryCode instance.
new(code: &[u8; 2]) -> Option<Self>244     pub fn new(code: &[u8; 2]) -> Option<Self> {
245         if code != CountryCode::UNKNOWN_COUNTRY_CODE
246             && !code.iter().all(|x| (*x as char).is_ascii_alphabetic())
247         {
248             None
249         } else {
250             Some(Self((*code).to_ascii_uppercase().try_into().ok()?))
251         }
252     }
253 }
254 
255 impl From<CountryCode> for [u8; 2] {
from(item: CountryCode) -> [u8; 2]256     fn from(item: CountryCode) -> [u8; 2] {
257         item.0
258     }
259 }
260 
261 impl TryFrom<String> for CountryCode {
262     type Error = Error;
try_from(item: String) -> Result<Self, Self::Error>263     fn try_from(item: String) -> Result<Self, Self::Error> {
264         let code = item.as_bytes().try_into().map_err(|_| Error::BadParameters)?;
265         Self::new(code).ok_or(Error::BadParameters)
266     }
267 }
268 
269 /// The response of the UciManager::core_get_device_info() method.
270 #[derive(Debug, Clone, PartialEq, Eq)]
271 pub struct GetDeviceInfoResponse {
272     /// Status
273     pub status: StatusCode,
274     /// The UCI version.
275     pub uci_version: u16,
276     /// The MAC version.
277     pub mac_version: u16,
278     /// The physical version.
279     pub phy_version: u16,
280     /// The UCI test version.
281     pub uci_test_version: u16,
282     /// The vendor spec info.
283     pub vendor_spec_info: Vec<u8>,
284 }
285 
286 /// The raw UCI message for the vendor commands.
287 #[derive(Debug, Clone, PartialEq, Eq)]
288 pub struct RawUciMessage {
289     /// The group id of the message.
290     pub gid: u32,
291     /// The opcode of the message.
292     pub oid: u32,
293     /// The payload of the message.
294     pub payload: Vec<u8>,
295 }
296 
297 impl From<UciControlPacket> for RawUciMessage {
from(packet: UciControlPacket) -> Self298     fn from(packet: UciControlPacket) -> Self {
299         Self {
300             gid: packet.get_group_id().into(),
301             oid: packet.get_opcode() as u32,
302             payload: packet.to_raw_payload(),
303         }
304     }
305 }
306 
307 #[cfg(test)]
308 mod tests {
309     use super::*;
310 
311     #[test]
test_redacted_app_config_tlv()312     fn test_redacted_app_config_tlv() {
313         // The value of VendorId and StaticStsIv should be redacted.
314         let tlv = AppConfigTlv::new(AppConfigTlvType::VendorId, vec![12, 34]);
315         let format_str = format!("{tlv:?}");
316         assert!(format_str.contains("v: \"redacted\""));
317 
318         let tlv = AppConfigTlv::new(AppConfigTlvType::StaticStsIv, vec![12, 34]);
319         let format_str = format!("{tlv:?}");
320         assert!(format_str.contains("v: \"redacted\""));
321 
322         // The value of DeviceType should be printed normally.
323         let tlv = AppConfigTlv::new(AppConfigTlvType::DeviceType, vec![12, 34]);
324         let format_str = format!("{tlv:?}");
325         assert_eq!(format_str, "AppConfigTlv { cfg_id: DeviceType, v: [12, 34] }");
326     }
327 
328     #[test]
test_country_code()329     fn test_country_code() {
330         let _country_code_ascii: CountryCode = String::from("US").try_into().unwrap();
331         let _country_code_unknown: CountryCode = String::from("00").try_into().unwrap();
332         let country_code_invalid_1: Result<CountryCode, Error> = String::from("0S").try_into();
333         country_code_invalid_1.unwrap_err();
334         let country_code_invalid_2: Result<CountryCode, Error> = String::from("ÀÈ").try_into();
335         country_code_invalid_2.unwrap_err();
336     }
337 
338     #[test]
test_rf_test_config_tlvs_eq()339     fn test_rf_test_config_tlvs_eq() {
340         let tlv1 = RfTestConfigTlv { cfg_id: RfTestConfigTlvType::NumPackets, v: vec![10, 20] };
341         let tlv2 = RfTestConfigTlv { cfg_id: RfTestConfigTlvType::TStart, v: vec![30, 40] };
342 
343         let array1 = vec![tlv1.clone(), tlv2.clone()];
344         let array2 = vec![tlv2.clone(), tlv1.clone()]; // Different order
345 
346         // Test that arrays with the same elements in different orders are equal.
347         assert!(rf_test_config_tlvs_eq(&array1, &array2));
348 
349         let tlv3 = RfTestConfigTlv {
350             cfg_id: RfTestConfigTlvType::TWin,
351             v: vec![70, 80], // Different value
352         };
353 
354         let array3 = vec![tlv1.clone(), tlv3.clone()];
355 
356         // Test that arrays with different elements are not equal.
357         assert!(!rf_test_config_tlvs_eq(&array1, &array3));
358     }
359 }
360