1 use crate::packets::uci;
2 use crate::MacAddress;
3 
4 /// [UCI] 8.3 Application Configuration Parameters.
5 /// Sub-session Key provided for Provisioned STS for Responder specific Key mode
6 /// (STS_CONFIG equal to 0x04).
7 #[derive(Clone, PartialEq, Eq)]
8 pub enum SubSessionKey {
9     None,
10     Short([u8; 16]),
11     Extended([u8; 32]),
12 }
13 
14 /// [UCI] 8.3 Application Configuration Parameters.
15 /// The configuration is initially filled with default values from the
16 /// specification.
17 /// See [UCI] Table 45: APP Configuration Parameters IDs
18 /// for the format of each parameter and the default value.
19 /// Mandatory APP configuration parameters are declared as optional,
20 /// and must be set before moving the session from SESSION_STATE_INIT to
21 /// SESSION_STATE_IDLE.
22 #[derive(Clone, PartialEq, Eq)]
23 pub struct AppConfig {
24     pub device_type: Option<uci::DeviceType>,
25     pub ranging_round_usage: Option<uci::RangingRoundUsage>,
26     pub sts_config: uci::StsConfig,
27     pub multi_node_mode: Option<uci::MultiNodeMode>,
28     channel_number: uci::ChannelNumber,
29     /// Number of Controlees(N) 1<=N<=8 (Default is 1)
30     pub number_of_controlees: u8,
31     /// MAC Address of the UWBS itself participating in UWB session.
32     /// The short address (2 bytes) or extended MAC address (8 bytes)
33     /// shall be indicated via MAC_ADDRESS_MODE config.
34     pub device_mac_address: Option<MacAddress>,
35     /// MAC Address list(N) for NUMBER_OF_CONTROLEES
36     /// devices participating in UWB Session.
37     ///
38     /// The size of this list shall be:
39     /// - equal to 1 when MULTI_NODE_MODE is set 0x00 (O2O).
40     /// - ranging from 1 to 8 when MULTI_NODE_MODE is set to 0x01 (O2M).
41     pub dst_mac_address: Vec<MacAddress>,
42     slot_duration: u16,
43     pub ranging_duration: u32,
44     sts_index: u32,
45     mac_fcs_type: uci::MacFcsType,
46     ranging_round_control: u8,
47     aoa_result_req: uci::AoaResultReq,
48     pub session_info_ntf_config: uci::SessionInfoNtfConfig,
49     near_proximity_config: u16,
50     far_proximity_config: u16,
51     pub device_role: Option<uci::DeviceRole>,
52     rframe_config: uci::RframeConfig,
53     rssi_reporting: uci::RssiReporting,
54     preamble_code_index: u8,
55     sfd_id: u8,
56     psdu_data_rate: uci::PsduDataRate,
57     preamble_duration: uci::PreambleDuration,
58     link_layer_mode: uci::LinkLayerMode,
59     data_repetition_count: u8,
60     ranging_time_struct: uci::RangingTimeStruct,
61     slots_per_rr: u8,
62     aoa_bound_config: [u16; 4],
63     prf_mode: uci::PrfMode,
64     cap_size_range: [u8; 2],
65     tx_jitter_window_size: u8,
66     pub schedule_mode: Option<uci::ScheduleMode>,
67     key_rotation: uci::KeyRotation,
68     key_rotation_rate: u8,
69     session_priority: u8,
70     pub mac_address_mode: uci::MacAddressMode,
71     vendor_id: u16,
72     static_sts_iv: [u8; 6],
73     number_of_sts_segments: u8,
74     max_rr_retry: u16,
75     uwb_initiation_time: u64,
76     hopping_mode: uci::HoppingMode,
77     block_stride_length: u8,
78     result_report_config: u8,
79     pub in_band_termination_attempt_count: u8,
80     sub_session_id: u32,
81     bprf_phr_data_rate: uci::BprfPhrDataRate,
82     max_number_of_measurements: u16,
83     sts_length: uci::StsLength,
84     min_frames_per_rr: u8,
85     mtu_size: u16,
86     inter_frame_interval: u8,
87     session_key: Vec<u8>,
88     sub_session_key: SubSessionKey,
89     pub session_data_transfer_status_ntf_config: uci::SessionDataTransferStatusNtfConfig,
90     session_time_base: [u8; 9],
91     application_data_endpoint: u8,
92 }
93 
94 impl Default for AppConfig {
default() -> Self95     fn default() -> Self {
96         AppConfig {
97             device_type: None,
98             ranging_round_usage: None,
99             sts_config: uci::StsConfig::Static,
100             multi_node_mode: None,
101             channel_number: uci::ChannelNumber::ChannelNumber9,
102             number_of_controlees: 1,
103             device_mac_address: None,
104             dst_mac_address: vec![],
105             slot_duration: 2400,
106             ranging_duration: 200,
107             sts_index: 0,
108             mac_fcs_type: uci::MacFcsType::Crc16,
109             // The default is 0x03 when Time Scheduled Ranging is used,
110             // 0x06 when Contention-based Ranging is used.
111             ranging_round_control: 0x06,
112             aoa_result_req: uci::AoaResultReq::AoaEnabled,
113             session_info_ntf_config: uci::SessionInfoNtfConfig::Enable,
114             near_proximity_config: 0,
115             far_proximity_config: 20000,
116             device_role: None,
117             rframe_config: uci::RframeConfig::Sp3,
118             rssi_reporting: uci::RssiReporting::Disable,
119             preamble_code_index: 10,
120             sfd_id: 2,
121             psdu_data_rate: uci::PsduDataRate::DataRate6m81,
122             preamble_duration: uci::PreambleDuration::Duration64Symbols,
123             link_layer_mode: uci::LinkLayerMode::BypassMode,
124             data_repetition_count: 0,
125             ranging_time_struct: uci::RangingTimeStruct::BlockBasedScheduling,
126             slots_per_rr: 25,
127             aoa_bound_config: [0; 4],
128             prf_mode: uci::PrfMode::BprfMode,
129             // Default for Octet[0] is SLOTS_PER_RR - 1
130             cap_size_range: [24, 5],
131             tx_jitter_window_size: 0,
132             schedule_mode: None,
133             key_rotation: uci::KeyRotation::Disable,
134             key_rotation_rate: 0,
135             session_priority: 50,
136             mac_address_mode: uci::MacAddressMode::Mode0,
137             vendor_id: 0,
138             static_sts_iv: [0; 6],
139             number_of_sts_segments: 1,
140             max_rr_retry: 0,
141             uwb_initiation_time: 0,
142             hopping_mode: uci::HoppingMode::Disable,
143             block_stride_length: 0,
144             result_report_config: 0x01,
145             in_band_termination_attempt_count: 1,
146             sub_session_id: 0, // XX
147             bprf_phr_data_rate: uci::BprfPhrDataRate::DataRate850k,
148             max_number_of_measurements: 0,
149             sts_length: uci::StsLength::Length64Symbols,
150             min_frames_per_rr: 4,
151             mtu_size: 0, // XX
152             inter_frame_interval: 1,
153             session_key: vec![],
154             sub_session_key: SubSessionKey::None,
155             session_data_transfer_status_ntf_config:
156                 uci::SessionDataTransferStatusNtfConfig::Disable,
157             session_time_base: [0; 9],
158             application_data_endpoint: 0,
159         }
160     }
161 }
162 
163 impl AppConfig {
164     /// Set the APP configuration value with the selected identifier
165     /// and value. Returns `Ok` if the identifier is known and the value
166     /// well formatted, `Err` otherwise.
set(&mut self, id: uci::AppConfigTlvType, value: &[u8]) -> anyhow::Result<()>167     pub fn set(&mut self, id: uci::AppConfigTlvType, value: &[u8]) -> anyhow::Result<()> {
168         fn try_parse<T: TryFrom<u8, Error = u8>>(value: &[u8]) -> anyhow::Result<T> {
169             T::try_from(u8::from_le_bytes(value.try_into()?)).map_err(anyhow::Error::msg)
170         }
171 
172         fn try_parse_u8(value: &[u8]) -> anyhow::Result<u8> {
173             Ok(u8::from_le_bytes(value.try_into()?))
174         }
175 
176         fn try_parse_u16(value: &[u8]) -> anyhow::Result<u16> {
177             Ok(u16::from_le_bytes(value.try_into()?))
178         }
179 
180         fn try_parse_u32(value: &[u8]) -> anyhow::Result<u32> {
181             Ok(u32::from_le_bytes(value.try_into()?))
182         }
183 
184         fn try_parse_u64(value: &[u8]) -> anyhow::Result<u64> {
185             Ok(u64::from_le_bytes(value.try_into()?))
186         }
187 
188         match id {
189             uci::AppConfigTlvType::DeviceType => self.device_type = Some(try_parse(value)?),
190             uci::AppConfigTlvType::RangingRoundUsage => {
191                 self.ranging_round_usage = Some(try_parse(value)?)
192             }
193             uci::AppConfigTlvType::StsConfig => self.sts_config = try_parse(value)?,
194             uci::AppConfigTlvType::MultiNodeMode => self.multi_node_mode = Some(try_parse(value)?),
195             uci::AppConfigTlvType::ChannelNumber => self.channel_number = try_parse(value)?,
196             uci::AppConfigTlvType::NumberOfControlees => {
197                 self.number_of_controlees = try_parse_u8(value)?
198             }
199             uci::AppConfigTlvType::DeviceMacAddress => {
200                 self.device_mac_address = Some(match self.mac_address_mode {
201                     uci::MacAddressMode::Mode0 => MacAddress::Short(value.try_into()?),
202                     uci::MacAddressMode::Mode1 => unimplemented!(),
203                     uci::MacAddressMode::Mode2 => MacAddress::Extended(value.try_into()?),
204                 })
205             }
206             uci::AppConfigTlvType::DstMacAddress => {
207                 let mac_address_size = match self.mac_address_mode {
208                     uci::MacAddressMode::Mode0 => 2,
209                     uci::MacAddressMode::Mode1 => unimplemented!(),
210                     uci::MacAddressMode::Mode2 => 8,
211                 };
212                 if value.len() != self.number_of_controlees as usize * mac_address_size {
213                     log::error!(
214                         "invalid dst_mac_address len: expected {}x{}, got {}",
215                         self.number_of_controlees,
216                         mac_address_size,
217                         value.len()
218                     );
219                     anyhow::bail!("invalid dst_mac_address len")
220                 }
221                 self.dst_mac_address = value
222                     .chunks(mac_address_size)
223                     .map(|value| match self.mac_address_mode {
224                         uci::MacAddressMode::Mode0 => MacAddress::Short(value.try_into().unwrap()),
225                         uci::MacAddressMode::Mode1 => unimplemented!(),
226                         uci::MacAddressMode::Mode2 => {
227                             MacAddress::Extended(value.try_into().unwrap())
228                         }
229                     })
230                     .collect();
231             }
232             uci::AppConfigTlvType::SlotDuration => self.slot_duration = try_parse_u16(value)?,
233             uci::AppConfigTlvType::RangingDuration => self.ranging_duration = try_parse_u32(value)?,
234             uci::AppConfigTlvType::StsIndex => self.sts_index = try_parse_u32(value)?,
235             uci::AppConfigTlvType::MacFcsType => self.mac_fcs_type = try_parse(value)?,
236             uci::AppConfigTlvType::RangingRoundControl => {
237                 self.ranging_round_control = try_parse_u8(value)?
238             }
239             uci::AppConfigTlvType::AoaResultReq => self.aoa_result_req = try_parse(value)?,
240             uci::AppConfigTlvType::SessionInfoNtfConfig => {
241                 self.session_info_ntf_config = try_parse(value)?
242             }
243             uci::AppConfigTlvType::NearProximityConfig => {
244                 self.near_proximity_config = try_parse_u16(value)?
245             }
246             uci::AppConfigTlvType::FarProximityConfig => {
247                 self.far_proximity_config = try_parse_u16(value)?
248             }
249             uci::AppConfigTlvType::DeviceRole => self.device_role = Some(try_parse(value)?),
250             uci::AppConfigTlvType::RframeConfig => self.rframe_config = try_parse(value)?,
251             uci::AppConfigTlvType::RssiReporting => self.rssi_reporting = try_parse(value)?,
252             uci::AppConfigTlvType::PreambleCodeIndex => {
253                 self.preamble_code_index = try_parse_u8(value)?
254             }
255             uci::AppConfigTlvType::SfdId => self.sfd_id = try_parse_u8(value)?,
256             uci::AppConfigTlvType::PsduDataRate => self.psdu_data_rate = try_parse(value)?,
257             uci::AppConfigTlvType::PreambleDuration => self.preamble_duration = try_parse(value)?,
258             uci::AppConfigTlvType::LinkLayerMode => self.link_layer_mode = try_parse(value)?,
259             uci::AppConfigTlvType::DataRepetitionCount => {
260                 self.data_repetition_count = try_parse_u8(value)?
261             }
262             uci::AppConfigTlvType::RangingTimeStruct => {
263                 self.ranging_time_struct = try_parse(value)?
264             }
265             uci::AppConfigTlvType::SlotsPerRr => self.slots_per_rr = try_parse_u8(value)?,
266             uci::AppConfigTlvType::AoaBoundConfig => {
267                 if value.len() != 8 {
268                     log::error!(
269                         "invalid aoa_bound_config len: expected 8, got {}",
270                         value.len()
271                     );
272                     anyhow::bail!("invalid aoa_bound_config len")
273                 }
274                 self.aoa_bound_config = [
275                     u16::from_le_bytes([value[0], value[1]]),
276                     u16::from_le_bytes([value[2], value[3]]),
277                     u16::from_le_bytes([value[4], value[5]]),
278                     u16::from_le_bytes([value[6], value[7]]),
279                 ]
280             }
281             uci::AppConfigTlvType::PrfMode => self.prf_mode = try_parse(value)?,
282             uci::AppConfigTlvType::CapSizeRange => self.cap_size_range = value.try_into()?,
283             uci::AppConfigTlvType::TxJitterWindowSize => {
284                 self.tx_jitter_window_size = try_parse_u8(value)?
285             }
286             uci::AppConfigTlvType::ScheduleMode => self.schedule_mode = Some(try_parse(value)?),
287             uci::AppConfigTlvType::KeyRotation => self.key_rotation = try_parse(value)?,
288             uci::AppConfigTlvType::KeyRotationRate => self.key_rotation_rate = try_parse_u8(value)?,
289             uci::AppConfigTlvType::SessionPriority => self.session_priority = try_parse_u8(value)?,
290             uci::AppConfigTlvType::MacAddressMode => self.mac_address_mode = try_parse(value)?,
291             uci::AppConfigTlvType::VendorId => self.vendor_id = try_parse_u16(value)?,
292             uci::AppConfigTlvType::StaticStsIv => self.static_sts_iv = value.try_into()?,
293             uci::AppConfigTlvType::NumberOfStsSegments => {
294                 self.number_of_sts_segments = try_parse_u8(value)?
295             }
296             uci::AppConfigTlvType::MaxRrRetry => self.max_rr_retry = try_parse_u16(value)?,
297             uci::AppConfigTlvType::UwbInitiationTime => {
298                 // Implement backward compatiblity for UCI 1.0
299                 // where the value is 4 bytes instead of 8.
300                 self.uwb_initiation_time = match value.len() {
301                     4 => try_parse_u32(value)? as u64,
302                     _ => try_parse_u64(value)?,
303                 }
304             }
305             uci::AppConfigTlvType::HoppingMode => self.hopping_mode = try_parse(value)?,
306             uci::AppConfigTlvType::BlockStrideLength => {
307                 self.block_stride_length = try_parse_u8(value)?
308             }
309             uci::AppConfigTlvType::ResultReportConfig => {
310                 self.result_report_config = try_parse_u8(value)?
311             }
312             uci::AppConfigTlvType::InBandTerminationAttemptCount => {
313                 self.in_band_termination_attempt_count = try_parse_u8(value)?
314             }
315             uci::AppConfigTlvType::SubSessionId => self.sub_session_id = try_parse_u32(value)?,
316             uci::AppConfigTlvType::BprfPhrDataRate => self.bprf_phr_data_rate = try_parse(value)?,
317             uci::AppConfigTlvType::MaxNumberOfMeasurements => {
318                 self.max_number_of_measurements = try_parse_u16(value)?
319             }
320             uci::AppConfigTlvType::StsLength => self.sts_length = try_parse(value)?,
321             uci::AppConfigTlvType::MinFramesPerRr => self.min_frames_per_rr = try_parse_u8(value)?,
322             uci::AppConfigTlvType::MtuSize => self.mtu_size = try_parse_u16(value)?,
323             uci::AppConfigTlvType::InterFrameInterval => {
324                 self.inter_frame_interval = try_parse_u8(value)?
325             }
326             uci::AppConfigTlvType::SessionKey => self.session_key = value.to_vec(),
327             uci::AppConfigTlvType::SubSessionKey => {
328                 self.sub_session_key = match value.len() {
329                     16 => SubSessionKey::Short(value.try_into().unwrap()),
330                     32 => SubSessionKey::Extended(value.try_into().unwrap()),
331                     _ => anyhow::bail!("invalid sub-session key size {}", value.len()),
332                 }
333             }
334             uci::AppConfigTlvType::SessionDataTransferStatusNtfConfig => {
335                 self.session_data_transfer_status_ntf_config = try_parse(value)?
336             }
337             uci::AppConfigTlvType::SessionTimeBase => self.session_time_base = value.try_into()?,
338             uci::AppConfigTlvType::ApplicationDataEndpoint => {
339                 self.application_data_endpoint = try_parse_u8(value)?
340             }
341 
342             uci::AppConfigTlvType::CccHopModeKey
343             | uci::AppConfigTlvType::CccUwbTime0
344             | uci::AppConfigTlvType::CccRangingProtocolVer
345             | uci::AppConfigTlvType::CccUwbConfigId
346             | uci::AppConfigTlvType::CccPulseshapeCombo
347             | uci::AppConfigTlvType::CccUrskTtl
348             | uci::AppConfigTlvType::CccLastIndexUsed
349             | uci::AppConfigTlvType::NbOfRangeMeasurements
350             | uci::AppConfigTlvType::NbOfAzimuthMeasurements
351             | uci::AppConfigTlvType::NbOfElevationMeasurements
352             | uci::AppConfigTlvType::EnableDiagnostics
353             | uci::AppConfigTlvType::DiagramsFrameReportsFields => {
354                 log::error!("unsupported vendor config type {:?}", id);
355                 anyhow::bail!("unsupported vendor config type {:?}", id)
356             }
357             _ => {
358                 log::error!("unsupported app config type {:?}", id);
359                 anyhow::bail!("unsupported app config type {:?}", id)
360             }
361         }
362         Ok(())
363     }
364 
365     /// Retrieve the APP configuration value with the selected identifier
366     /// Returns `Ok` if the identifier is known, `Err` otherwise.
get(&self, id: uci::AppConfigTlvType) -> anyhow::Result<Vec<u8>>367     pub fn get(&self, id: uci::AppConfigTlvType) -> anyhow::Result<Vec<u8>> {
368         match id {
369             uci::AppConfigTlvType::DeviceType => Ok(vec![self
370                 .device_type
371                 .ok_or(anyhow::anyhow!("optional app config not set"))?
372                 .into()]),
373             uci::AppConfigTlvType::RangingRoundUsage => Ok(vec![self
374                 .ranging_round_usage
375                 .ok_or(anyhow::anyhow!("optional app config not set"))?
376                 .into()]),
377             uci::AppConfigTlvType::StsConfig => Ok(vec![self.sts_config.into()]),
378             uci::AppConfigTlvType::MultiNodeMode => Ok(vec![self
379                 .multi_node_mode
380                 .ok_or(anyhow::anyhow!("optional app config not set"))?
381                 .into()]),
382             uci::AppConfigTlvType::ChannelNumber => Ok(vec![self.channel_number.into()]),
383             uci::AppConfigTlvType::NumberOfControlees => Ok(vec![self.number_of_controlees]),
384             uci::AppConfigTlvType::DeviceMacAddress => Ok(self
385                 .device_mac_address
386                 .ok_or(anyhow::anyhow!("optional app config not set"))?
387                 .into()),
388             uci::AppConfigTlvType::DstMacAddress => Ok(self
389                 .dst_mac_address
390                 .iter()
391                 .flat_map(Vec::<u8>::from)
392                 .collect()),
393             uci::AppConfigTlvType::SlotDuration => Ok(self.slot_duration.to_le_bytes().to_vec()),
394             uci::AppConfigTlvType::RangingDuration => {
395                 Ok(self.ranging_duration.to_le_bytes().to_vec())
396             }
397             uci::AppConfigTlvType::StsIndex => Ok(self.sts_index.to_le_bytes().to_vec()),
398             uci::AppConfigTlvType::MacFcsType => Ok(vec![self.mac_fcs_type.into()]),
399             uci::AppConfigTlvType::RangingRoundControl => Ok(vec![self.ranging_round_control]),
400             uci::AppConfigTlvType::AoaResultReq => Ok(vec![self.aoa_result_req.into()]),
401             uci::AppConfigTlvType::SessionInfoNtfConfig => {
402                 Ok(vec![self.session_info_ntf_config.into()])
403             }
404             uci::AppConfigTlvType::NearProximityConfig => {
405                 Ok(self.near_proximity_config.to_le_bytes().to_vec())
406             }
407             uci::AppConfigTlvType::FarProximityConfig => {
408                 Ok(self.far_proximity_config.to_le_bytes().to_vec())
409             }
410             uci::AppConfigTlvType::DeviceRole => Ok(vec![self
411                 .device_role
412                 .ok_or(anyhow::anyhow!("optional app config not set"))?
413                 .into()]),
414             uci::AppConfigTlvType::RframeConfig => Ok(vec![self.rframe_config.into()]),
415             uci::AppConfigTlvType::RssiReporting => Ok(vec![self.rssi_reporting.into()]),
416             uci::AppConfigTlvType::PreambleCodeIndex => Ok(vec![self.preamble_code_index]),
417             uci::AppConfigTlvType::SfdId => Ok(vec![self.sfd_id]),
418             uci::AppConfigTlvType::PsduDataRate => Ok(vec![self.psdu_data_rate.into()]),
419             uci::AppConfigTlvType::PreambleDuration => Ok(vec![self.preamble_duration.into()]),
420             uci::AppConfigTlvType::LinkLayerMode => Ok(vec![self.link_layer_mode.into()]),
421             uci::AppConfigTlvType::DataRepetitionCount => Ok(vec![self.data_repetition_count]),
422             uci::AppConfigTlvType::RangingTimeStruct => Ok(vec![self.ranging_time_struct.into()]),
423             uci::AppConfigTlvType::SlotsPerRr => Ok(vec![self.slots_per_rr]),
424             uci::AppConfigTlvType::AoaBoundConfig => Ok(self
425                 .aoa_bound_config
426                 .iter()
427                 .copied()
428                 .flat_map(u16::to_le_bytes)
429                 .collect()),
430             uci::AppConfigTlvType::PrfMode => Ok(vec![self.prf_mode.into()]),
431             uci::AppConfigTlvType::CapSizeRange => Ok(self.cap_size_range.to_vec()),
432             uci::AppConfigTlvType::TxJitterWindowSize => Ok(vec![self.tx_jitter_window_size]),
433             uci::AppConfigTlvType::ScheduleMode => Ok(vec![self
434                 .schedule_mode
435                 .ok_or(anyhow::anyhow!("optional app config not set"))?
436                 .into()]),
437             uci::AppConfigTlvType::KeyRotation => Ok(vec![self.key_rotation.into()]),
438             uci::AppConfigTlvType::KeyRotationRate => Ok(vec![self.key_rotation_rate]),
439             uci::AppConfigTlvType::SessionPriority => Ok(vec![self.session_priority]),
440             uci::AppConfigTlvType::MacAddressMode => Ok(vec![self.mac_address_mode.into()]),
441             uci::AppConfigTlvType::VendorId => Ok(self.vendor_id.to_le_bytes().to_vec()),
442             uci::AppConfigTlvType::StaticStsIv => Ok(self.static_sts_iv.to_vec()),
443             uci::AppConfigTlvType::NumberOfStsSegments => Ok(vec![self.number_of_sts_segments]),
444             uci::AppConfigTlvType::MaxRrRetry => Ok(self.max_rr_retry.to_le_bytes().to_vec()),
445             uci::AppConfigTlvType::UwbInitiationTime => {
446                 Ok(self.uwb_initiation_time.to_le_bytes().to_vec())
447             }
448             uci::AppConfigTlvType::HoppingMode => Ok(vec![self.hopping_mode.into()]),
449             uci::AppConfigTlvType::BlockStrideLength => Ok(vec![self.block_stride_length]),
450             uci::AppConfigTlvType::ResultReportConfig => Ok(vec![self.result_report_config]),
451             uci::AppConfigTlvType::InBandTerminationAttemptCount => {
452                 Ok(vec![self.in_band_termination_attempt_count])
453             }
454             uci::AppConfigTlvType::SubSessionId => Ok(self.sub_session_id.to_le_bytes().to_vec()),
455             uci::AppConfigTlvType::BprfPhrDataRate => Ok(vec![self.bprf_phr_data_rate.into()]),
456             uci::AppConfigTlvType::MaxNumberOfMeasurements => {
457                 Ok(self.max_number_of_measurements.to_le_bytes().to_vec())
458             }
459             uci::AppConfigTlvType::StsLength => Ok(vec![self.sts_length.into()]),
460             uci::AppConfigTlvType::MinFramesPerRr => Ok(vec![self.min_frames_per_rr]),
461             uci::AppConfigTlvType::MtuSize => Ok(self.mtu_size.to_le_bytes().to_vec()),
462             uci::AppConfigTlvType::InterFrameInterval => Ok(vec![self.inter_frame_interval]),
463             uci::AppConfigTlvType::SessionKey => Ok(self.session_key.clone()),
464             uci::AppConfigTlvType::SubSessionKey => Ok(match self.sub_session_key {
465                 SubSessionKey::None => vec![],
466                 SubSessionKey::Short(key) => key.to_vec(),
467                 SubSessionKey::Extended(key) => key.to_vec(),
468             }),
469             uci::AppConfigTlvType::SessionDataTransferStatusNtfConfig => {
470                 Ok(vec![self.session_data_transfer_status_ntf_config.into()])
471             }
472             uci::AppConfigTlvType::SessionTimeBase => Ok(self.session_time_base.to_vec()),
473             uci::AppConfigTlvType::ApplicationDataEndpoint => {
474                 Ok(vec![self.application_data_endpoint])
475             }
476 
477             uci::AppConfigTlvType::CccHopModeKey
478             | uci::AppConfigTlvType::CccUwbTime0
479             | uci::AppConfigTlvType::CccRangingProtocolVer
480             | uci::AppConfigTlvType::CccUwbConfigId
481             | uci::AppConfigTlvType::CccPulseshapeCombo
482             | uci::AppConfigTlvType::CccUrskTtl
483             | uci::AppConfigTlvType::CccLastIndexUsed
484             | uci::AppConfigTlvType::NbOfRangeMeasurements
485             | uci::AppConfigTlvType::NbOfAzimuthMeasurements
486             | uci::AppConfigTlvType::NbOfElevationMeasurements
487             | uci::AppConfigTlvType::EnableDiagnostics
488             | uci::AppConfigTlvType::DiagramsFrameReportsFields => {
489                 log::error!("unsupported vendor config type {:?}", id);
490                 anyhow::bail!("unsupported vendor config type {:?}", id)
491             }
492             _ => {
493                 log::error!("unsupported app config type {:?}", id);
494                 anyhow::bail!("unsupported app config type {:?}", id)
495             }
496         }
497     }
498 
is_compatible_for_ranging(&self, peer_config: &Self) -> bool499     pub fn is_compatible_for_ranging(&self, peer_config: &Self) -> bool {
500         self.device_role != peer_config.device_role
501             && self.device_type != peer_config.device_type
502             && peer_config
503                 .dst_mac_address
504                 .contains(&self.device_mac_address.unwrap())
505             && self
506                 .dst_mac_address
507                 .contains(&peer_config.device_mac_address.unwrap())
508     }
509 
can_start_data_transfer(&self) -> bool510     pub fn can_start_data_transfer(&self) -> bool {
511         self.device_role == Some(uci::DeviceRole::Initiator)
512     }
513 
can_receive_data_transfer(&self) -> bool514     pub fn can_receive_data_transfer(&self) -> bool {
515         self.device_role == Some(uci::DeviceRole::Responder)
516     }
517 }
518