• 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     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     SessionState, SessionType, SessionUpdateControllerMulticastListNtfV1Payload,
34     SessionUpdateControllerMulticastListNtfV2Payload,
35     SessionUpdateControllerMulticastListRspV1Payload,
36     SessionUpdateControllerMulticastListRspV2Payload, ShortAddressDlTdoaRangingMeasurement,
37     ShortAddressOwrAoaRangingMeasurement, ShortAddressTwoWayRangingMeasurement, StatusCode,
38     UpdateMulticastListAction,
39 };
40 pub(crate) use uwb_uci_packets::{UciControlPacket, UciDataPacket, UciDataPacketHal};
41 
42 use crate::error::Error;
43 
44 /// The type of the session identifier.
45 pub type SessionId = u32;
46 /// The type of the sub-session identifier.
47 pub type SubSessionId = u32;
48 /// The type of the session handle.
49 pub type SessionHandle = u32;
50 /// Generic type used to represent either a session id or session handle.
51 pub type SessionToken = u32;
52 
53 /// Wrap the original AppConfigTlv type to redact the PII fields when logging.
54 #[derive(Clone, PartialEq)]
55 pub struct AppConfigTlv {
56     tlv: RawAppConfigTlv,
57 }
58 
59 /// Controlee Status Enum compatible with different Fira version.
60 pub enum ControleeStatusList {
61     /// Controlee status defined in Fira 1.x.
62     V1(Vec<ControleeStatusV1>),
63     /// Controlee status defined in Fira 2.0.
64     V2(Vec<ControleeStatusV2>),
65 }
66 
67 /// UCI major version
68 #[derive(FromPrimitive, ToPrimitive, PartialEq, Clone)]
69 #[repr(u8)]
70 pub enum UCIMajorVersion {
71     /// Version 1.x
72     V1 = 1,
73     /// Version 2.0
74     V2 = 2,
75 }
76 
77 impl std::fmt::Debug for AppConfigTlv {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error>78     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
79         static REDACTED_STR: &str = "redacted";
80 
81         let mut ds = f.debug_struct("AppConfigTlv");
82         ds.field("cfg_id", &self.tlv.cfg_id);
83         if self.tlv.cfg_id == AppConfigTlvType::VendorId
84             || self.tlv.cfg_id == AppConfigTlvType::StaticStsIv
85         {
86             ds.field("v", &REDACTED_STR);
87         } else {
88             ds.field("v", &self.tlv.v);
89         }
90         ds.finish()
91     }
92 }
93 
94 impl AppConfigTlv {
95     /// Create a wrapper of uwb_uci_packets::AppConfigTlv.
96     ///
97     /// The argument is the same as the uwb_uci_packets::AppConfigTlv's struct.
new(cfg_id: AppConfigTlvType, v: Vec<u8>) -> Self98     pub fn new(cfg_id: AppConfigTlvType, v: Vec<u8>) -> Self {
99         Self { tlv: RawAppConfigTlv { cfg_id, v } }
100     }
101 
102     /// Consumes the outter wrapper type, returning the wrapped uwb_uci_packets::AppConfigTlv.
into_inner(self) -> RawAppConfigTlv103     pub fn into_inner(self) -> RawAppConfigTlv {
104         self.tlv
105     }
106 }
107 
108 impl From<RawAppConfigTlv> for AppConfigTlv {
from(tlv: RawAppConfigTlv) -> Self109     fn from(tlv: RawAppConfigTlv) -> Self {
110         Self { tlv }
111     }
112 }
113 
114 impl std::ops::Deref for AppConfigTlv {
115     type Target = RawAppConfigTlv;
deref(&self) -> &Self::Target116     fn deref(&self) -> &Self::Target {
117         &self.tlv
118     }
119 }
120 
121 impl std::ops::DerefMut for AppConfigTlv {
deref_mut(&mut self) -> &mut Self::Target122     fn deref_mut(&mut self) -> &mut Self::Target {
123         &mut self.tlv
124     }
125 }
126 
127 /// Compare if two AppConfigTlv array are equal. Convert the array to HashMap before comparing
128 /// because the order of TLV elements doesn't matter.
129 #[allow(dead_code)]
app_config_tlvs_eq(a: &[AppConfigTlv], b: &[AppConfigTlv]) -> bool130 pub fn app_config_tlvs_eq(a: &[AppConfigTlv], b: &[AppConfigTlv]) -> bool {
131     app_config_tlvs_to_map(a) == app_config_tlvs_to_map(b)
132 }
133 
app_config_tlvs_to_map( tlvs: &[AppConfigTlv], ) -> HashMap<AppConfigTlvType, &Vec<u8>, RandomState>134 fn app_config_tlvs_to_map(
135     tlvs: &[AppConfigTlv],
136 ) -> HashMap<AppConfigTlvType, &Vec<u8>, RandomState> {
137     HashMap::from_iter(tlvs.iter().map(|config| (config.cfg_id, &config.v)))
138 }
139 
140 /// Compare if two DeviceConfigTlv array are equal. Convert the array to HashMap before comparing
141 /// because the order of TLV elements doesn't matter.
142 #[allow(dead_code)]
device_config_tlvs_eq(a: &[DeviceConfigTlv], b: &[DeviceConfigTlv]) -> bool143 pub fn device_config_tlvs_eq(a: &[DeviceConfigTlv], b: &[DeviceConfigTlv]) -> bool {
144     device_config_tlvs_to_map(a) == device_config_tlvs_to_map(b)
145 }
146 
device_config_tlvs_to_map( tlvs: &[DeviceConfigTlv], ) -> HashMap<DeviceConfigId, &Vec<u8>, RandomState>147 fn device_config_tlvs_to_map(
148     tlvs: &[DeviceConfigTlv],
149 ) -> HashMap<DeviceConfigId, &Vec<u8>, RandomState> {
150     HashMap::from_iter(tlvs.iter().map(|config| (config.cfg_id, &config.v)))
151 }
152 
153 /// Compare if two RadarConfigTlv array are equal. Convert the array to HashMap before comparing
154 /// because the order of TLV elements doesn't matter.
155 #[allow(dead_code)]
radar_config_tlvs_eq(a: &[RadarConfigTlv], b: &[RadarConfigTlv]) -> bool156 pub fn radar_config_tlvs_eq(a: &[RadarConfigTlv], b: &[RadarConfigTlv]) -> bool {
157     radar_config_tlvs_to_map(a) == radar_config_tlvs_to_map(b)
158 }
159 
radar_config_tlvs_to_map( tlvs: &[RadarConfigTlv], ) -> HashMap<RadarConfigTlvType, &Vec<u8>, RandomState>160 fn radar_config_tlvs_to_map(
161     tlvs: &[RadarConfigTlv],
162 ) -> HashMap<RadarConfigTlvType, &Vec<u8>, RandomState> {
163     HashMap::from_iter(tlvs.iter().map(|config| (config.cfg_id, &config.v)))
164 }
165 
166 /// The response of the UciManager::core_set_config() method.
167 #[derive(Debug, Clone, PartialEq)]
168 pub struct CoreSetConfigResponse {
169     /// The status code of the response.
170     pub status: StatusCode,
171     /// The status of each config TLV.
172     pub config_status: Vec<DeviceConfigStatus>,
173 }
174 
175 /// The response of the UciManager::session_set_app_config() method.
176 #[derive(Debug, Clone, PartialEq)]
177 pub struct SetAppConfigResponse {
178     /// The status code of the response.
179     pub status: StatusCode,
180     /// The status of each config TLV.
181     pub config_status: Vec<AppConfigStatus>,
182 }
183 
184 /// The response of the UciManager::android_set_radar_config() method.
185 #[derive(Debug, Clone, PartialEq)]
186 pub struct AndroidRadarConfigResponse {
187     /// The status code of the response.
188     pub status: StatusCode,
189     /// The status of each config TLV.
190     pub config_status: Vec<RadarConfigStatus>,
191 }
192 
193 /// The response from UciManager::(session_update_controller_multicast_list() method.
194 #[derive(Debug, Clone, PartialEq, Eq)]
195 pub struct SessionUpdateControllerMulticastResponse {
196     /// The status code of the response.
197     pub status: StatusCode,
198     /// Controlee Status
199     pub status_list: Vec<ControleeStatusV2>,
200 }
201 
202 /// The response from UciManager::session_update_dt_tag_ranging_rounds() method.
203 #[derive(Debug, Clone, PartialEq, Eq)]
204 pub struct SessionUpdateDtTagRangingRoundsResponse {
205     /// The status code of the response.
206     pub status: StatusCode,
207     /// Indexes of unsuccessful ranging rounds.
208     pub ranging_round_indexes: Vec<u8>,
209 }
210 
211 /// The country code struct that contains 2 uppercase ASCII characters.
212 #[derive(Debug, Clone, PartialEq, Eq)]
213 pub struct CountryCode([u8; 2]);
214 
215 impl CountryCode {
216     const UNKNOWN_COUNTRY_CODE: &'static [u8] = "00".as_bytes();
217 
218     /// Create a CountryCode instance.
new(code: &[u8; 2]) -> Option<Self>219     pub fn new(code: &[u8; 2]) -> Option<Self> {
220         if code != CountryCode::UNKNOWN_COUNTRY_CODE
221             && !code.iter().all(|x| (*x as char).is_ascii_alphabetic())
222         {
223             None
224         } else {
225             Some(Self((*code).to_ascii_uppercase().try_into().ok()?))
226         }
227     }
228 }
229 
230 impl From<CountryCode> for [u8; 2] {
from(item: CountryCode) -> [u8; 2]231     fn from(item: CountryCode) -> [u8; 2] {
232         item.0
233     }
234 }
235 
236 impl TryFrom<String> for CountryCode {
237     type Error = Error;
try_from(item: String) -> Result<Self, Self::Error>238     fn try_from(item: String) -> Result<Self, Self::Error> {
239         let code = item.as_bytes().try_into().map_err(|_| Error::BadParameters)?;
240         Self::new(code).ok_or(Error::BadParameters)
241     }
242 }
243 
244 /// absolute time in UWBS Time domain(ms) when this configuration applies
245 #[derive(Debug, Clone, PartialEq, Copy)]
246 pub struct UpdateTime([u8; 8]);
247 
248 impl UpdateTime {
249     /// Create a UpdateTime instance.
new(update_time: &[u8; 8]) -> Option<Self>250     pub fn new(update_time: &[u8; 8]) -> Option<Self> {
251         Some(Self(*update_time))
252     }
253 }
254 
255 impl From<UpdateTime> for [u8; 8] {
from(item: UpdateTime) -> [u8; 8]256     fn from(item: UpdateTime) -> [u8; 8] {
257         item.0
258     }
259 }
260 
261 /// The response of the UciManager::core_get_device_info() method.
262 #[derive(Debug, Clone, PartialEq, Eq)]
263 pub struct GetDeviceInfoResponse {
264     /// Status
265     pub status: StatusCode,
266     /// The UCI version.
267     pub uci_version: u16,
268     /// The MAC version.
269     pub mac_version: u16,
270     /// The physical version.
271     pub phy_version: u16,
272     /// The UCI test version.
273     pub uci_test_version: u16,
274     /// The vendor spec info.
275     pub vendor_spec_info: Vec<u8>,
276 }
277 
278 /// The raw UCI message for the vendor commands.
279 #[derive(Debug, Clone, PartialEq, Eq)]
280 pub struct RawUciMessage {
281     /// The group id of the message.
282     pub gid: u32,
283     /// The opcode of the message.
284     pub oid: u32,
285     /// The payload of the message.
286     pub payload: Vec<u8>,
287 }
288 
289 impl From<UciControlPacket> for RawUciMessage {
from(packet: UciControlPacket) -> Self290     fn from(packet: UciControlPacket) -> Self {
291         Self {
292             gid: packet.get_group_id().into(),
293             oid: packet.get_opcode() as u32,
294             payload: packet.to_raw_payload(),
295         }
296     }
297 }
298 
299 #[cfg(test)]
300 mod tests {
301     use super::*;
302 
303     #[test]
test_redacted_app_config_tlv()304     fn test_redacted_app_config_tlv() {
305         // The value of VendorId and StaticStsIv should be redacted.
306         let tlv = AppConfigTlv::new(AppConfigTlvType::VendorId, vec![12, 34]);
307         let format_str = format!("{tlv:?}");
308         assert!(format_str.contains("v: \"redacted\""));
309 
310         let tlv = AppConfigTlv::new(AppConfigTlvType::StaticStsIv, vec![12, 34]);
311         let format_str = format!("{tlv:?}");
312         assert!(format_str.contains("v: \"redacted\""));
313 
314         // The value of DeviceType should be printed normally.
315         let tlv = AppConfigTlv::new(AppConfigTlvType::DeviceType, vec![12, 34]);
316         let format_str = format!("{tlv:?}");
317         assert_eq!(format_str, "AppConfigTlv { cfg_id: DeviceType, v: [12, 34] }");
318     }
319 
320     #[test]
test_country_code()321     fn test_country_code() {
322         let _country_code_ascii: CountryCode = String::from("US").try_into().unwrap();
323         let _country_code_unknown: CountryCode = String::from("00").try_into().unwrap();
324         let country_code_invalid_1: Result<CountryCode, Error> = String::from("0S").try_into();
325         country_code_invalid_1.unwrap_err();
326         let country_code_invalid_2: Result<CountryCode, Error> = String::from("ÀÈ").try_into();
327         country_code_invalid_2.unwrap_err();
328     }
329 }
330