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 #![allow(missing_docs)] 16 17 use std::collections::HashMap; 18 19 use crate::params::aliro_app_config_params::AliroAppConfigParams; 20 use crate::params::ccc_app_config_params::CccAppConfigParams; 21 use crate::params::ccc_started_app_config_params::CccStartedAppConfigParams; 22 use crate::params::fira_app_config_params::FiraAppConfigParams; 23 use crate::params::uci_packets::{AppConfigTlv, AppConfigTlvType, SessionState, SessionType}; 24 25 pub(super) type AppConfigTlvMap = HashMap<AppConfigTlvType, Vec<u8>>; 26 27 /// The application configuration parameters of the UWB session. It is used to generate the 28 /// parameters for the SESSION_SET_APP_CONFIG_CMD, or converted from the result of the 29 /// SESSION_GET_APP_CONFIG_CMD. 30 #[derive(Debug, Clone, PartialEq, Eq)] 31 pub enum AppConfigParams { 32 Fira(FiraAppConfigParams), 33 Ccc(CccAppConfigParams), 34 CccStarted(CccStartedAppConfigParams), 35 Aliro(AliroAppConfigParams), 36 } 37 38 impl AppConfigParams { 39 /// Generate the TLV list from the params. generate_tlvs(&self) -> Vec<AppConfigTlv>40 pub fn generate_tlvs(&self) -> Vec<AppConfigTlv> { 41 Self::config_map_to_tlvs(self.generate_config_map()) 42 } 43 44 /// Generate the updated TLV list from the difference between this and the previous params. generate_updated_tlvs( &self, prev_params: &Self, session_state: SessionState, ) -> Option<Vec<AppConfigTlv>>45 pub fn generate_updated_tlvs( 46 &self, 47 prev_params: &Self, 48 session_state: SessionState, 49 ) -> Option<Vec<AppConfigTlv>> { 50 Some(Self::config_map_to_tlvs( 51 self.generate_updated_config_map(prev_params, session_state)?, 52 )) 53 } 54 config_map_to_tlvs(config_map: AppConfigTlvMap) -> Vec<AppConfigTlv>55 fn config_map_to_tlvs(config_map: AppConfigTlvMap) -> Vec<AppConfigTlv> { 56 config_map.into_iter().map(|(cfg_id, v)| AppConfigTlv::new(cfg_id, v)).collect() 57 } 58 generate_config_map(&self) -> AppConfigTlvMap59 pub(super) fn generate_config_map(&self) -> AppConfigTlvMap { 60 match self { 61 Self::Fira(params) => params.generate_config_map(), 62 Self::Ccc(params) => params.generate_config_map(), 63 Self::Aliro(params) => params.generate_config_map(), 64 _ => HashMap::new(), 65 } 66 } 67 generate_updated_config_map( &self, prev_params: &Self, session_state: SessionState, ) -> Option<AppConfigTlvMap>68 pub(super) fn generate_updated_config_map( 69 &self, 70 prev_params: &Self, 71 session_state: SessionState, 72 ) -> Option<AppConfigTlvMap> { 73 let config_map = self.generate_config_map(); 74 let prev_config_map = prev_params.generate_config_map(); 75 76 match (self, prev_params) { 77 (Self::Fira(_), Self::Fira(_)) => { 78 let updated_config_map = Self::diff_config_map(config_map, prev_config_map); 79 if FiraAppConfigParams::is_config_updatable(&updated_config_map, session_state) { 80 Some(updated_config_map) 81 } else { 82 None 83 } 84 } 85 (Self::Ccc(_), Self::Ccc(_)) => { 86 let updated_config_map = Self::diff_config_map(config_map, prev_config_map); 87 if CccAppConfigParams::is_config_updatable(&updated_config_map, session_state) { 88 Some(updated_config_map) 89 } else { 90 None 91 } 92 } 93 (Self::Aliro(_), Self::Aliro(_)) => { 94 let updated_config_map = Self::diff_config_map(config_map, prev_config_map); 95 if AliroAppConfigParams::is_config_updatable(&updated_config_map, session_state) { 96 Some(updated_config_map) 97 } else { 98 None 99 } 100 } 101 _ => None, 102 } 103 } 104 is_type_matched(&self, session_type: SessionType) -> bool105 pub fn is_type_matched(&self, session_type: SessionType) -> bool { 106 match self { 107 Self::Fira(_) => { 108 session_type == SessionType::FiraDataTransferSession 109 || session_type == SessionType::FiraRangingSession 110 || session_type == SessionType::FiraRangingAndInBandDataSession 111 || session_type == SessionType::FiraRangingOnlyPhase 112 || session_type == SessionType::FiraInBandDataPhase 113 || session_type == SessionType::FiraRangingWithDataPhase 114 } 115 Self::Ccc(_) | Self::CccStarted(_) => session_type == SessionType::Ccc, 116 Self::Aliro(_) => session_type == SessionType::Aliro, 117 } 118 } 119 diff_config_map( config_map: AppConfigTlvMap, prev_config_map: AppConfigTlvMap, ) -> AppConfigTlvMap120 fn diff_config_map( 121 config_map: AppConfigTlvMap, 122 prev_config_map: AppConfigTlvMap, 123 ) -> AppConfigTlvMap { 124 // The key sets of both map should be the same. 125 debug_assert!( 126 config_map.len() == prev_config_map.len() 127 && config_map.keys().all(|key| prev_config_map.contains_key(key)) 128 ); 129 130 let mut updated_config_map = HashMap::new(); 131 for (key, value) in config_map.into_iter() { 132 if !matches!(prev_config_map.get(&key), Some(prev_value) if prev_value == &value) { 133 updated_config_map.insert(key, value); 134 } 135 } 136 updated_config_map 137 } 138 } 139