1 /* 2 * Copyright 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #include <cstring> 17 18 #include <base/logging.h> 19 20 #include "mca_api.h" 21 #include "mca_defs.h" 22 #include "mcap_test_mcl.h" 23 24 namespace SYSTEM_BT_TOOLS_MCAP_TOOL { 25 26 McapMcl::McapMcl(btmcap_test_interface_t* mcap_test_interface, 27 tMCA_HANDLE mcap_handle, const RawAddress& peer_bd_addr) 28 : _mdl_list() { 29 _mcap_handle = mcap_handle; 30 _mcap_test_interface = mcap_test_interface; 31 memcpy(_peer_bd_addr.address, peer_bd_addr.address, 32 sizeof(_peer_bd_addr.address)); 33 } 34 35 bool McapMcl::Connect(uint16_t ctrl_psm, uint16_t sec_mask) { 36 tMCA_RESULT ret = _mcap_test_interface->connect_mcl( 37 _mcap_handle, _peer_bd_addr, ctrl_psm, sec_mask); 38 LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << (int)ret; 39 return ret == MCA_SUCCESS; 40 } 41 42 bool McapMcl::Disconnect() { 43 if (!IsConnected()) { 44 LOG(ERROR) << "MCL is not connected"; 45 return false; 46 } 47 tMCA_RESULT ret = _mcap_test_interface->disconnect_mcl(_mcl_handle); 48 LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << (int)ret; 49 return ret == MCA_SUCCESS; 50 } 51 52 McapMdl* McapMcl::AllocateMdl(tMCA_DEP mdep_handle, uint16_t mdl_id, 53 uint8_t dep_id, uint8_t cfg) { 54 if (!IsConnected()) { 55 LOG(ERROR) << "MCL is not connected"; 56 return nullptr; 57 } 58 if (FindMdlById(mdl_id) != nullptr) { 59 LOG(ERROR) << "mdl_id=" << mdl_id << "already exists"; 60 return nullptr; 61 } 62 if (!HasAvailableMdl()) { 63 LOG(ERROR) << "No more avaible MDL, currently " << _mdl_list.size(); 64 return nullptr; 65 } 66 _mdl_list.push_back(McapMdl(_mcap_test_interface, _mcl_handle, mdep_handle, 67 mdl_id, dep_id, cfg)); 68 return &_mdl_list[_mdl_list.size() - 1]; 69 } 70 71 bool McapMcl::CreateMdl(tMCA_DEP mdep_handle, uint16_t data_psm, 72 uint16_t mdl_id, uint8_t peer_dep_id, uint8_t cfg, 73 bool should_connect) { 74 if (!IsConnected()) { 75 LOG(ERROR) << "MCL is not connected"; 76 return false; 77 } 78 McapMdl* mcap_mdl = FindMdlById(mdl_id); 79 if (!mcap_mdl) { 80 LOG(INFO) << "mdl_id=" << mdl_id << "does not exists, creating new one"; 81 mcap_mdl = AllocateMdl(mdep_handle, mdl_id, peer_dep_id, cfg); 82 if (!mcap_mdl) { 83 return false; 84 } 85 } 86 if (mcap_mdl->IsConnected()) { 87 LOG(ERROR) << "mdl_id=" << mdl_id << "is already connected with handle " 88 << (int)mcap_mdl->GetHandle(); 89 return false; 90 } 91 return mcap_mdl->Create(data_psm, should_connect); 92 } 93 94 bool McapMcl::DataChannelConfig() { 95 tMCA_RESULT ret = _mcap_test_interface->data_channel_config( 96 _mcl_handle, get_test_channel_config()); 97 LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << (int)ret; 98 return ret == MCA_SUCCESS; 99 } 100 101 bool McapMcl::CreateMdlResponse(tMCA_DEP mdep_handle, uint16_t mdl_id, 102 uint8_t my_dep_id, uint8_t cfg) { 103 if (!IsConnected()) { 104 LOG(ERROR) << "MCL is not connected"; 105 return false; 106 } 107 McapMdl* mcap_mdl = FindMdlById(mdl_id); 108 if (!mcap_mdl) { 109 LOG(INFO) << "mdl_id=" << mdl_id << " does not exists, creating new one"; 110 mcap_mdl = AllocateMdl(mdep_handle, mdl_id, my_dep_id, cfg); 111 if (!mcap_mdl) { 112 LOG(ERROR) << "MDL cannot be created"; 113 return false; 114 } 115 } 116 if (mcap_mdl->IsConnected()) { 117 LOG(INFO) << "mdl_id=" << mdl_id << " is already connected with handle " 118 << (int)mcap_mdl->GetHandle() << ", updating context"; 119 mcap_mdl->UpdateContext(mdep_handle, my_dep_id, cfg); 120 } 121 return mcap_mdl->CreateResponse(); 122 } 123 124 bool McapMcl::AbortMdl() { 125 tMCA_RESULT ret = _mcap_test_interface->abort_mdl(_mcl_handle); 126 LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << (int)ret; 127 return ret == MCA_SUCCESS; 128 } 129 130 bool McapMcl::DeleteMdl(uint16_t mdl_id) { 131 tMCA_RESULT ret = _mcap_test_interface->delete_mdl(_mcl_handle, mdl_id); 132 LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << (int)ret; 133 return ret == MCA_SUCCESS; 134 } 135 136 RawAddress& McapMcl::GetPeerAddress() { return _peer_bd_addr; } 137 138 void McapMcl::SetHandle(tMCA_CL handle) { _mcl_handle = handle; } 139 140 tMCA_CL McapMcl::GetHandle() const { return _mcl_handle; } 141 142 void McapMcl::SetMtu(uint16_t mtu) { _control_mtu = mtu; } 143 144 uint16_t McapMcl::GetMtu() { return _control_mtu; } 145 146 McapMdl* McapMcl::FindMdlById(uint16_t mdl_id) { 147 for (McapMdl& mdl : _mdl_list) { 148 if (mdl.GetId() == mdl_id) { 149 return &mdl; 150 } 151 } 152 return nullptr; 153 } 154 155 McapMdl* McapMcl::FindMdlByHandle(tMCA_DL mdl_handle) { 156 for (McapMdl& mdl : _mdl_list) { 157 if (mdl.GetHandle() == mdl_handle) { 158 return &mdl; 159 } 160 } 161 return nullptr; 162 } 163 164 void McapMcl::RemoveAllMdl() { _mdl_list.clear(); } 165 166 void McapMcl::RemoveMdl(uint16_t mdl_id) { 167 LOG(INFO) << "Removing MDL id " << (int)mdl_id; 168 for (std::vector<McapMdl>::iterator it = _mdl_list.begin(); 169 it != _mdl_list.end(); ++it) { 170 if (it->GetId() == mdl_id) { 171 _mdl_list.erase(it); 172 LOG(INFO) << "Removed MDL id " << (int)mdl_id; 173 return; 174 } 175 } 176 } 177 178 void McapMcl::ResetAllMdl() { 179 for (McapMdl& mcap_mdl : _mdl_list) { 180 mcap_mdl.SetHandle(0); 181 mcap_mdl.SetMtu(0); 182 mcap_mdl.SetResponseCode(-1); 183 } 184 } 185 186 void McapMcl::ResetMdl(uint16_t mdl_id) { 187 LOG(INFO) << "Closing MDL id " << (int)mdl_id; 188 McapMdl* mcap_mdl = FindMdlById(mdl_id); 189 if (!mcap_mdl) { 190 LOG(ERROR) << "Cannot find MDL for id " << (int)mdl_id; 191 return; 192 } 193 if (mcap_mdl->IsConnected()) { 194 LOG(ERROR) << "MDL " << (int)mdl_id << " is still connected"; 195 return; 196 } 197 mcap_mdl->SetHandle(0); 198 mcap_mdl->SetMtu(0); 199 mcap_mdl->SetResponseCode(-1); 200 } 201 202 bool McapMcl::IsConnected() { return _mcl_handle > 0; } 203 204 int McapMcl::ConnectedMdlCount() { 205 int count = 0; 206 for (McapMdl& mcap_mdl : _mdl_list) { 207 if (mcap_mdl.IsConnected()) { 208 count++; 209 } 210 } 211 return count; 212 } 213 214 bool McapMcl::HasAvailableMdl() { return ConnectedMdlCount() < MCA_NUM_MDLS; } 215 216 } // namespace SYSTEM_BT_TOOLS_MCAP_TOOL 217