You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
216 lines
6.3 KiB
216 lines
6.3 KiB
/* |
|
* Copyright (C) 2017 The Android Open Source Project |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
#include <cstring> |
|
|
|
#include <base/logging.h> |
|
|
|
#include "mca_api.h" |
|
#include "mca_defs.h" |
|
#include "mcap_test_mcl.h" |
|
|
|
namespace SYSTEM_BT_TOOLS_MCAP_TOOL { |
|
|
|
McapMcl::McapMcl(btmcap_test_interface_t* mcap_test_interface, |
|
tMCA_HANDLE mcap_handle, const RawAddress& peer_bd_addr) |
|
: _mdl_list() { |
|
_mcap_handle = mcap_handle; |
|
_mcap_test_interface = mcap_test_interface; |
|
memcpy(_peer_bd_addr.address, peer_bd_addr.address, |
|
sizeof(_peer_bd_addr.address)); |
|
} |
|
|
|
bool McapMcl::Connect(uint16_t ctrl_psm, uint16_t sec_mask) { |
|
tMCA_RESULT ret = _mcap_test_interface->connect_mcl( |
|
_mcap_handle, _peer_bd_addr, ctrl_psm, sec_mask); |
|
LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << (int)ret; |
|
return ret == MCA_SUCCESS; |
|
} |
|
|
|
bool McapMcl::Disconnect() { |
|
if (!IsConnected()) { |
|
LOG(ERROR) << "MCL is not connected"; |
|
return false; |
|
} |
|
tMCA_RESULT ret = _mcap_test_interface->disconnect_mcl(_mcl_handle); |
|
LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << (int)ret; |
|
return ret == MCA_SUCCESS; |
|
} |
|
|
|
McapMdl* McapMcl::AllocateMdl(tMCA_DEP mdep_handle, uint16_t mdl_id, |
|
uint8_t dep_id, uint8_t cfg) { |
|
if (!IsConnected()) { |
|
LOG(ERROR) << "MCL is not connected"; |
|
return nullptr; |
|
} |
|
if (FindMdlById(mdl_id) != nullptr) { |
|
LOG(ERROR) << "mdl_id=" << mdl_id << "already exists"; |
|
return nullptr; |
|
} |
|
if (!HasAvailableMdl()) { |
|
LOG(ERROR) << "No more avaible MDL, currently " << _mdl_list.size(); |
|
return nullptr; |
|
} |
|
_mdl_list.push_back(McapMdl(_mcap_test_interface, _mcl_handle, mdep_handle, |
|
mdl_id, dep_id, cfg)); |
|
return &_mdl_list[_mdl_list.size() - 1]; |
|
} |
|
|
|
bool McapMcl::CreateMdl(tMCA_DEP mdep_handle, uint16_t data_psm, |
|
uint16_t mdl_id, uint8_t peer_dep_id, uint8_t cfg, |
|
bool should_connect) { |
|
if (!IsConnected()) { |
|
LOG(ERROR) << "MCL is not connected"; |
|
return false; |
|
} |
|
McapMdl* mcap_mdl = FindMdlById(mdl_id); |
|
if (!mcap_mdl) { |
|
LOG(INFO) << "mdl_id=" << mdl_id << "does not exists, creating new one"; |
|
mcap_mdl = AllocateMdl(mdep_handle, mdl_id, peer_dep_id, cfg); |
|
if (!mcap_mdl) { |
|
return false; |
|
} |
|
} |
|
if (mcap_mdl->IsConnected()) { |
|
LOG(ERROR) << "mdl_id=" << mdl_id << "is already connected with handle " |
|
<< (int)mcap_mdl->GetHandle(); |
|
return false; |
|
} |
|
return mcap_mdl->Create(data_psm, should_connect); |
|
} |
|
|
|
bool McapMcl::DataChannelConfig() { |
|
tMCA_RESULT ret = _mcap_test_interface->data_channel_config( |
|
_mcl_handle, get_test_channel_config()); |
|
LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << (int)ret; |
|
return ret == MCA_SUCCESS; |
|
} |
|
|
|
bool McapMcl::CreateMdlResponse(tMCA_DEP mdep_handle, uint16_t mdl_id, |
|
uint8_t my_dep_id, uint8_t cfg) { |
|
if (!IsConnected()) { |
|
LOG(ERROR) << "MCL is not connected"; |
|
return false; |
|
} |
|
McapMdl* mcap_mdl = FindMdlById(mdl_id); |
|
if (!mcap_mdl) { |
|
LOG(INFO) << "mdl_id=" << mdl_id << " does not exists, creating new one"; |
|
mcap_mdl = AllocateMdl(mdep_handle, mdl_id, my_dep_id, cfg); |
|
if (!mcap_mdl) { |
|
LOG(ERROR) << "MDL cannot be created"; |
|
return false; |
|
} |
|
} |
|
if (mcap_mdl->IsConnected()) { |
|
LOG(INFO) << "mdl_id=" << mdl_id << " is already connected with handle " |
|
<< (int)mcap_mdl->GetHandle() << ", updating context"; |
|
mcap_mdl->UpdateContext(mdep_handle, my_dep_id, cfg); |
|
} |
|
return mcap_mdl->CreateResponse(); |
|
} |
|
|
|
bool McapMcl::AbortMdl() { |
|
tMCA_RESULT ret = _mcap_test_interface->abort_mdl(_mcl_handle); |
|
LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << (int)ret; |
|
return ret == MCA_SUCCESS; |
|
} |
|
|
|
bool McapMcl::DeleteMdl(uint16_t mdl_id) { |
|
tMCA_RESULT ret = _mcap_test_interface->delete_mdl(_mcl_handle, mdl_id); |
|
LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << (int)ret; |
|
return ret == MCA_SUCCESS; |
|
} |
|
|
|
RawAddress& McapMcl::GetPeerAddress() { return _peer_bd_addr; } |
|
|
|
void McapMcl::SetHandle(tMCA_CL handle) { _mcl_handle = handle; } |
|
|
|
tMCA_CL McapMcl::GetHandle() const { return _mcl_handle; } |
|
|
|
void McapMcl::SetMtu(uint16_t mtu) { _control_mtu = mtu; } |
|
|
|
uint16_t McapMcl::GetMtu() { return _control_mtu; } |
|
|
|
McapMdl* McapMcl::FindMdlById(uint16_t mdl_id) { |
|
for (McapMdl& mdl : _mdl_list) { |
|
if (mdl.GetId() == mdl_id) { |
|
return &mdl; |
|
} |
|
} |
|
return nullptr; |
|
} |
|
|
|
McapMdl* McapMcl::FindMdlByHandle(tMCA_DL mdl_handle) { |
|
for (McapMdl& mdl : _mdl_list) { |
|
if (mdl.GetHandle() == mdl_handle) { |
|
return &mdl; |
|
} |
|
} |
|
return nullptr; |
|
} |
|
|
|
void McapMcl::RemoveAllMdl() { _mdl_list.clear(); } |
|
|
|
void McapMcl::RemoveMdl(uint16_t mdl_id) { |
|
LOG(INFO) << "Removing MDL id " << (int)mdl_id; |
|
for (std::vector<McapMdl>::iterator it = _mdl_list.begin(); |
|
it != _mdl_list.end(); ++it) { |
|
if (it->GetId() == mdl_id) { |
|
_mdl_list.erase(it); |
|
LOG(INFO) << "Removed MDL id " << (int)mdl_id; |
|
return; |
|
} |
|
} |
|
} |
|
|
|
void McapMcl::ResetAllMdl() { |
|
for (McapMdl& mcap_mdl : _mdl_list) { |
|
mcap_mdl.SetHandle(0); |
|
mcap_mdl.SetMtu(0); |
|
mcap_mdl.SetResponseCode(-1); |
|
} |
|
} |
|
|
|
void McapMcl::ResetMdl(uint16_t mdl_id) { |
|
LOG(INFO) << "Closing MDL id " << (int)mdl_id; |
|
McapMdl* mcap_mdl = FindMdlById(mdl_id); |
|
if (!mcap_mdl) { |
|
LOG(ERROR) << "Cannot find MDL for id " << (int)mdl_id; |
|
return; |
|
} |
|
if (mcap_mdl->IsConnected()) { |
|
LOG(ERROR) << "MDL " << (int)mdl_id << " is still connected"; |
|
return; |
|
} |
|
mcap_mdl->SetHandle(0); |
|
mcap_mdl->SetMtu(0); |
|
mcap_mdl->SetResponseCode(-1); |
|
} |
|
|
|
bool McapMcl::IsConnected() { return _mcl_handle > 0; } |
|
|
|
int McapMcl::ConnectedMdlCount() { |
|
int count = 0; |
|
for (McapMdl& mcap_mdl : _mdl_list) { |
|
if (mcap_mdl.IsConnected()) { |
|
count++; |
|
} |
|
} |
|
return count; |
|
} |
|
|
|
bool McapMcl::HasAvailableMdl() { return ConnectedMdlCount() < MCA_NUM_MDLS; } |
|
|
|
} // namespace SYSTEM_BT_TOOLS_MCAP_TOOL
|
|
|