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.
686 lines
23 KiB
686 lines
23 KiB
/*
|
|
* Copyright 2019 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.
|
|
*/
|
|
|
|
#define LOG_TAG "bt_shim_btm"
|
|
|
|
#include <algorithm>
|
|
#include <chrono>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
#include <mutex>
|
|
|
|
#include "bta/include/bta_api.h"
|
|
#include "main/shim/btm.h"
|
|
#include "main/shim/controller.h"
|
|
#include "main/shim/entry.h"
|
|
#include "main/shim/helpers.h"
|
|
#include "main/shim/shim.h"
|
|
#include "stack/btm/btm_dev.h"
|
|
#include "stack/btm/btm_int_types.h"
|
|
#include "types/bt_transport.h"
|
|
#include "types/raw_address.h"
|
|
|
|
#include "gd/hci/le_advertising_manager.h"
|
|
#include "gd/hci/le_scanning_manager.h"
|
|
#include "gd/neighbor/connectability.h"
|
|
#include "gd/neighbor/discoverability.h"
|
|
#include "gd/neighbor/inquiry.h"
|
|
#include "gd/neighbor/name.h"
|
|
#include "gd/neighbor/page.h"
|
|
#include "gd/security/security_module.h"
|
|
|
|
extern tBTM_CB btm_cb;
|
|
|
|
static constexpr size_t kRemoteDeviceNameLength = 248;
|
|
|
|
static constexpr bool kActiveScanning = true;
|
|
static constexpr bool kPassiveScanning = false;
|
|
|
|
using BtmRemoteDeviceName = tBTM_REMOTE_DEV_NAME;
|
|
|
|
extern void btm_process_cancel_complete(uint8_t status, uint8_t mode);
|
|
extern void btm_process_inq_complete(uint8_t status, uint8_t result_type);
|
|
extern void btm_ble_process_adv_addr(RawAddress& raw_address,
|
|
tBLE_ADDR_TYPE* address_type);
|
|
extern void btm_ble_process_adv_pkt_cont(
|
|
uint16_t event_type, uint8_t address_type, const RawAddress& raw_address,
|
|
uint8_t primary_phy, uint8_t secondary_phy, uint8_t advertising_sid,
|
|
int8_t tx_power, int8_t rssi, uint16_t periodic_adv_int, uint8_t data_len,
|
|
uint8_t* data);
|
|
|
|
extern void btm_api_process_inquiry_result(const RawAddress& raw_address,
|
|
uint8_t page_scan_rep_mode,
|
|
DEV_CLASS device_class,
|
|
uint16_t clock_offset);
|
|
|
|
extern void btm_api_process_inquiry_result_with_rssi(RawAddress raw_address,
|
|
uint8_t page_scan_rep_mode,
|
|
DEV_CLASS device_class,
|
|
uint16_t clock_offset,
|
|
int8_t rssi);
|
|
|
|
extern void btm_api_process_extended_inquiry_result(
|
|
RawAddress raw_address, uint8_t page_scan_rep_mode, DEV_CLASS device_class,
|
|
uint16_t clock_offset, int8_t rssi, const uint8_t* eir_data,
|
|
size_t eir_len);
|
|
|
|
namespace bluetooth {
|
|
|
|
namespace shim {
|
|
|
|
bool Btm::ReadRemoteName::Start(RawAddress raw_address) {
|
|
std::unique_lock<std::mutex> lock(mutex_);
|
|
if (in_progress_) {
|
|
return false;
|
|
}
|
|
raw_address_ = raw_address;
|
|
in_progress_ = true;
|
|
return true;
|
|
}
|
|
|
|
void Btm::ReadRemoteName::Stop() {
|
|
std::unique_lock<std::mutex> lock(mutex_);
|
|
raw_address_ = RawAddress::kEmpty;
|
|
in_progress_ = false;
|
|
}
|
|
|
|
bool Btm::ReadRemoteName::IsInProgress() const { return in_progress_; }
|
|
std::string Btm::ReadRemoteName::AddressString() const {
|
|
return raw_address_.ToString();
|
|
}
|
|
|
|
void Btm::ScanningCallbacks::OnScannerRegistered(
|
|
const bluetooth::hci::Uuid app_uuid, bluetooth::hci::ScannerId scanner_id,
|
|
ScanningStatus status){};
|
|
|
|
void Btm::ScanningCallbacks::OnScanResult(
|
|
uint16_t event_type, uint8_t address_type, bluetooth::hci::Address address,
|
|
uint8_t primary_phy, uint8_t secondary_phy, uint8_t advertising_sid,
|
|
int8_t tx_power, int8_t rssi, uint16_t periodic_advertising_interval,
|
|
std::vector<uint8_t> advertising_data) {
|
|
tBLE_ADDR_TYPE ble_address_type = static_cast<tBLE_ADDR_TYPE>(address_type);
|
|
uint16_t extended_event_type = 0;
|
|
|
|
RawAddress raw_address;
|
|
RawAddress::FromString(address.ToString(), raw_address);
|
|
|
|
if (ble_address_type != BLE_ADDR_ANONYMOUS) {
|
|
btm_ble_process_adv_addr(raw_address, &ble_address_type);
|
|
}
|
|
|
|
btm_ble_process_adv_addr(raw_address, &ble_address_type);
|
|
btm_ble_process_adv_pkt_cont(extended_event_type, ble_address_type,
|
|
raw_address, primary_phy, secondary_phy,
|
|
advertising_sid, tx_power, rssi,
|
|
periodic_advertising_interval,
|
|
advertising_data.size(), &advertising_data[0]);
|
|
}
|
|
|
|
void Btm::ScanningCallbacks::OnTrackAdvFoundLost(
|
|
bluetooth::hci::AdvertisingFilterOnFoundOnLostInfo on_found_on_lost_info){};
|
|
void Btm::ScanningCallbacks::OnBatchScanReports(int client_if, int status,
|
|
int report_format,
|
|
int num_records,
|
|
std::vector<uint8_t> data){};
|
|
|
|
void Btm::ScanningCallbacks::OnBatchScanThresholdCrossed(int client_if){};
|
|
void Btm::ScanningCallbacks::OnTimeout(){};
|
|
void Btm::ScanningCallbacks::OnFilterEnable(bluetooth::hci::Enable enable,
|
|
uint8_t status){};
|
|
void Btm::ScanningCallbacks::OnFilterParamSetup(
|
|
uint8_t available_spaces, bluetooth::hci::ApcfAction action,
|
|
uint8_t status){};
|
|
void Btm::ScanningCallbacks::OnFilterConfigCallback(
|
|
bluetooth::hci::ApcfFilterType filter_type, uint8_t available_spaces,
|
|
bluetooth::hci::ApcfAction action, uint8_t status){};
|
|
|
|
Btm::Btm(os::Handler* handler, neighbor::InquiryModule* inquiry)
|
|
: scanning_timer_(handler), observing_timer_(handler) {
|
|
ASSERT(handler != nullptr);
|
|
ASSERT(inquiry != nullptr);
|
|
bluetooth::neighbor::InquiryCallbacks inquiry_callbacks = {
|
|
.result = std::bind(&Btm::OnInquiryResult, this, std::placeholders::_1),
|
|
.result_with_rssi =
|
|
std::bind(&Btm::OnInquiryResultWithRssi, this, std::placeholders::_1),
|
|
.extended_result =
|
|
std::bind(&Btm::OnExtendedInquiryResult, this, std::placeholders::_1),
|
|
.complete =
|
|
std::bind(&Btm::OnInquiryComplete, this, std::placeholders::_1)};
|
|
inquiry->RegisterCallbacks(std::move(inquiry_callbacks));
|
|
}
|
|
|
|
void Btm::OnInquiryResult(bluetooth::hci::InquiryResultView view) {
|
|
for (auto& response : view.GetInquiryResults()) {
|
|
btm_api_process_inquiry_result(
|
|
ToRawAddress(response.bd_addr_),
|
|
static_cast<uint8_t>(response.page_scan_repetition_mode_),
|
|
response.class_of_device_.data(), response.clock_offset_);
|
|
}
|
|
}
|
|
|
|
void Btm::OnInquiryResultWithRssi(
|
|
bluetooth::hci::InquiryResultWithRssiView view) {
|
|
for (auto& response : view.GetInquiryResults()) {
|
|
btm_api_process_inquiry_result_with_rssi(
|
|
ToRawAddress(response.address_),
|
|
static_cast<uint8_t>(response.page_scan_repetition_mode_),
|
|
response.class_of_device_.data(), response.clock_offset_,
|
|
response.rssi_);
|
|
}
|
|
}
|
|
|
|
void Btm::OnExtendedInquiryResult(
|
|
bluetooth::hci::ExtendedInquiryResultView view) {
|
|
constexpr size_t kMaxExtendedInquiryResponse = 240;
|
|
uint8_t gap_data_buffer[kMaxExtendedInquiryResponse];
|
|
uint8_t* data = nullptr;
|
|
size_t data_len = 0;
|
|
|
|
if (!view.GetExtendedInquiryResponse().empty()) {
|
|
bzero(gap_data_buffer, sizeof(gap_data_buffer));
|
|
uint8_t* p = gap_data_buffer;
|
|
for (auto gap_data : view.GetExtendedInquiryResponse()) {
|
|
*p++ = gap_data.data_.size() + sizeof(gap_data.data_type_);
|
|
*p++ = static_cast<uint8_t>(gap_data.data_type_);
|
|
p = (uint8_t*)memcpy(p, &gap_data.data_[0], gap_data.data_.size()) +
|
|
gap_data.data_.size();
|
|
}
|
|
data = gap_data_buffer;
|
|
data_len = p - data;
|
|
}
|
|
|
|
btm_api_process_extended_inquiry_result(
|
|
ToRawAddress(view.GetAddress()),
|
|
static_cast<uint8_t>(view.GetPageScanRepetitionMode()),
|
|
view.GetClassOfDevice().data(), view.GetClockOffset(), view.GetRssi(),
|
|
data, data_len);
|
|
}
|
|
|
|
void Btm::OnInquiryComplete(bluetooth::hci::ErrorCode status) {
|
|
limited_inquiry_active_ = false;
|
|
general_inquiry_active_ = false;
|
|
legacy_inquiry_complete_callback_((static_cast<uint16_t>(status) == 0)
|
|
? (BTM_SUCCESS)
|
|
: (BTM_ERR_PROCESSING),
|
|
active_inquiry_mode_);
|
|
|
|
active_inquiry_mode_ = kInquiryModeOff;
|
|
}
|
|
|
|
void Btm::SetStandardInquiryResultMode() {
|
|
GetInquiry()->SetStandardInquiryResultMode();
|
|
}
|
|
|
|
void Btm::SetInquiryWithRssiResultMode() {
|
|
GetInquiry()->SetInquiryWithRssiResultMode();
|
|
}
|
|
|
|
void Btm::SetExtendedInquiryResultMode() {
|
|
GetInquiry()->SetExtendedInquiryResultMode();
|
|
}
|
|
|
|
void Btm::SetInterlacedInquiryScan() { GetInquiry()->SetInterlacedScan(); }
|
|
|
|
void Btm::SetStandardInquiryScan() { GetInquiry()->SetStandardScan(); }
|
|
|
|
bool Btm::IsInterlacedScanSupported() const {
|
|
return controller_get_interface()->supports_interlaced_inquiry_scan();
|
|
}
|
|
|
|
/**
|
|
* One shot inquiry
|
|
*/
|
|
bool Btm::StartInquiry(
|
|
uint8_t mode, uint8_t duration, uint8_t max_responses,
|
|
LegacyInquiryCompleteCallback legacy_inquiry_complete_callback) {
|
|
switch (mode) {
|
|
case kInquiryModeOff:
|
|
LOG_INFO("%s Stopping inquiry mode", __func__);
|
|
if (limited_inquiry_active_ || general_inquiry_active_) {
|
|
GetInquiry()->StopInquiry();
|
|
limited_inquiry_active_ = false;
|
|
general_inquiry_active_ = false;
|
|
}
|
|
active_inquiry_mode_ = kInquiryModeOff;
|
|
break;
|
|
|
|
case kLimitedInquiryMode:
|
|
case kGeneralInquiryMode: {
|
|
if (mode == kLimitedInquiryMode) {
|
|
LOG_INFO(
|
|
|
|
"%s Starting limited inquiry mode duration:%hhd max responses:%hhd",
|
|
__func__, duration, max_responses);
|
|
limited_inquiry_active_ = true;
|
|
GetInquiry()->StartLimitedInquiry(duration, max_responses);
|
|
active_inquiry_mode_ = kLimitedInquiryMode;
|
|
} else {
|
|
LOG_INFO(
|
|
|
|
"%s Starting general inquiry mode duration:%hhd max responses:%hhd",
|
|
__func__, duration, max_responses);
|
|
general_inquiry_active_ = true;
|
|
GetInquiry()->StartGeneralInquiry(duration, max_responses);
|
|
legacy_inquiry_complete_callback_ = legacy_inquiry_complete_callback;
|
|
}
|
|
} break;
|
|
|
|
default:
|
|
LOG_WARN("%s Unknown inquiry mode:%d", __func__, mode);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void Btm::CancelInquiry() {
|
|
LOG_INFO("%s", __func__);
|
|
if (limited_inquiry_active_ || general_inquiry_active_) {
|
|
GetInquiry()->StopInquiry();
|
|
limited_inquiry_active_ = false;
|
|
general_inquiry_active_ = false;
|
|
}
|
|
}
|
|
|
|
bool Btm::IsInquiryActive() const {
|
|
return IsGeneralInquiryActive() || IsLimitedInquiryActive();
|
|
}
|
|
|
|
bool Btm::IsGeneralInquiryActive() const { return general_inquiry_active_; }
|
|
|
|
bool Btm::IsLimitedInquiryActive() const { return limited_inquiry_active_; }
|
|
|
|
/**
|
|
* Periodic
|
|
*/
|
|
bool Btm::StartPeriodicInquiry(uint8_t mode, uint8_t duration,
|
|
uint8_t max_responses, uint16_t max_delay,
|
|
uint16_t min_delay,
|
|
tBTM_INQ_RESULTS_CB* p_results_cb) {
|
|
switch (mode) {
|
|
case kInquiryModeOff:
|
|
limited_periodic_inquiry_active_ = false;
|
|
general_periodic_inquiry_active_ = false;
|
|
GetInquiry()->StopPeriodicInquiry();
|
|
break;
|
|
|
|
case kLimitedInquiryMode:
|
|
case kGeneralInquiryMode: {
|
|
if (mode == kLimitedInquiryMode) {
|
|
LOG_INFO("%s Starting limited periodic inquiry mode", __func__);
|
|
limited_periodic_inquiry_active_ = true;
|
|
GetInquiry()->StartLimitedPeriodicInquiry(duration, max_responses,
|
|
max_delay, min_delay);
|
|
} else {
|
|
LOG_INFO("%s Starting general periodic inquiry mode", __func__);
|
|
general_periodic_inquiry_active_ = true;
|
|
GetInquiry()->StartGeneralPeriodicInquiry(duration, max_responses,
|
|
max_delay, min_delay);
|
|
}
|
|
} break;
|
|
|
|
default:
|
|
LOG_WARN("%s Unknown inquiry mode:%d", __func__, mode);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Btm::IsGeneralPeriodicInquiryActive() const {
|
|
return general_periodic_inquiry_active_;
|
|
}
|
|
|
|
bool Btm::IsLimitedPeriodicInquiryActive() const {
|
|
return limited_periodic_inquiry_active_;
|
|
}
|
|
|
|
/**
|
|
* Discoverability
|
|
*/
|
|
|
|
bluetooth::neighbor::ScanParameters params_{
|
|
.interval = 0,
|
|
.window = 0,
|
|
};
|
|
|
|
void Btm::SetClassicGeneralDiscoverability(uint16_t window, uint16_t interval) {
|
|
params_.window = window;
|
|
params_.interval = interval;
|
|
|
|
GetInquiry()->SetScanActivity(params_);
|
|
GetDiscoverability()->StartGeneralDiscoverability();
|
|
}
|
|
|
|
void Btm::SetClassicLimitedDiscoverability(uint16_t window, uint16_t interval) {
|
|
params_.window = window;
|
|
params_.interval = interval;
|
|
GetInquiry()->SetScanActivity(params_);
|
|
GetDiscoverability()->StartLimitedDiscoverability();
|
|
}
|
|
|
|
void Btm::SetClassicDiscoverabilityOff() {
|
|
GetDiscoverability()->StopDiscoverability();
|
|
}
|
|
|
|
DiscoverabilityState Btm::GetClassicDiscoverabilityState() const {
|
|
DiscoverabilityState state{.mode = BTM_NON_DISCOVERABLE,
|
|
.interval = params_.interval,
|
|
.window = params_.window};
|
|
|
|
if (GetDiscoverability()->IsGeneralDiscoverabilityEnabled()) {
|
|
state.mode = BTM_GENERAL_DISCOVERABLE;
|
|
} else if (GetDiscoverability()->IsLimitedDiscoverabilityEnabled()) {
|
|
state.mode = BTM_LIMITED_DISCOVERABLE;
|
|
}
|
|
return state;
|
|
}
|
|
|
|
void Btm::SetLeGeneralDiscoverability() {
|
|
LOG_WARN("UNIMPLEMENTED %s", __func__);
|
|
}
|
|
|
|
void Btm::SetLeLimitedDiscoverability() {
|
|
LOG_WARN("UNIMPLEMENTED %s", __func__);
|
|
}
|
|
|
|
void Btm::SetLeDiscoverabilityOff() { LOG_WARN("UNIMPLEMENTED %s", __func__); }
|
|
|
|
DiscoverabilityState Btm::GetLeDiscoverabilityState() const {
|
|
DiscoverabilityState state{
|
|
.mode = kDiscoverableModeOff,
|
|
.interval = 0,
|
|
.window = 0,
|
|
};
|
|
LOG_WARN("UNIMPLEMENTED %s", __func__);
|
|
return state;
|
|
}
|
|
|
|
/**
|
|
* Connectability
|
|
*/
|
|
void Btm::SetClassicConnectibleOn() {
|
|
GetConnectability()->StartConnectability();
|
|
}
|
|
|
|
void Btm::SetClassicConnectibleOff() {
|
|
GetConnectability()->StopConnectability();
|
|
}
|
|
|
|
ConnectabilityState Btm::GetClassicConnectabilityState() const {
|
|
ConnectabilityState state{.interval = params_.interval,
|
|
.window = params_.window};
|
|
|
|
if (GetConnectability()->IsConnectable()) {
|
|
state.mode = BTM_CONNECTABLE;
|
|
} else {
|
|
state.mode = BTM_NON_CONNECTABLE;
|
|
}
|
|
return state;
|
|
}
|
|
|
|
void Btm::SetInterlacedPageScan() { GetPage()->SetInterlacedScan(); }
|
|
|
|
void Btm::SetStandardPageScan() { GetPage()->SetStandardScan(); }
|
|
|
|
void Btm::SetLeConnectibleOn() { LOG_WARN("UNIMPLEMENTED %s", __func__); }
|
|
|
|
void Btm::SetLeConnectibleOff() { LOG_WARN("UNIMPLEMENTED %s", __func__); }
|
|
|
|
ConnectabilityState Btm::GetLeConnectabilityState() const {
|
|
ConnectabilityState state{
|
|
.mode = kConnectibleModeOff,
|
|
.interval = 0,
|
|
.window = 0,
|
|
};
|
|
LOG_WARN("UNIMPLEMENTED %s", __func__);
|
|
return state;
|
|
}
|
|
|
|
bool Btm::UseLeLink(const RawAddress& raw_address) const {
|
|
if (GetAclManager()->HACK_GetHandle(ToGdAddress(raw_address)) != 0xFFFF) {
|
|
return false;
|
|
}
|
|
if (GetAclManager()->HACK_GetLeHandle(ToGdAddress(raw_address)) != 0xFFFF) {
|
|
return true;
|
|
}
|
|
// TODO(hsz): use correct transport by using storage records. For now assume
|
|
// LE for GATT and HID.
|
|
return true;
|
|
}
|
|
|
|
BtmStatus Btm::ReadClassicRemoteDeviceName(const RawAddress& raw_address,
|
|
tBTM_CMPL_CB* callback) {
|
|
if (!CheckClassicAclLink(raw_address)) {
|
|
return BTM_UNKNOWN_ADDR;
|
|
}
|
|
|
|
if (!classic_read_remote_name_.Start(raw_address)) {
|
|
LOG_INFO("%s Read remote name is currently busy address:%s", __func__,
|
|
raw_address.ToString().c_str());
|
|
return BTM_BUSY;
|
|
}
|
|
|
|
LOG_INFO("%s Start read name from address:%s", __func__,
|
|
raw_address.ToString().c_str());
|
|
GetName()->ReadRemoteNameRequest(
|
|
ToGdAddress(raw_address), hci::PageScanRepetitionMode::R1,
|
|
0 /* clock_offset */, hci::ClockOffsetValid::INVALID,
|
|
|
|
base::Bind(
|
|
[](tBTM_CMPL_CB* callback, ReadRemoteName* classic_read_remote_name,
|
|
hci::ErrorCode status, hci::Address address,
|
|
std::array<uint8_t, kRemoteDeviceNameLength> remote_name) {
|
|
RawAddress raw_address = ToRawAddress(address);
|
|
|
|
BtmRemoteDeviceName name{
|
|
.status = (static_cast<uint8_t>(status) == 0)
|
|
? (BTM_SUCCESS)
|
|
: (BTM_BAD_VALUE_RET),
|
|
.bd_addr = raw_address,
|
|
.length = kRemoteDeviceNameLength,
|
|
};
|
|
std::copy(remote_name.begin(), remote_name.end(),
|
|
name.remote_bd_name);
|
|
LOG_INFO("%s Finish read name from address:%s name:%s", __func__,
|
|
address.ToString().c_str(), name.remote_bd_name);
|
|
callback(&name);
|
|
classic_read_remote_name->Stop();
|
|
},
|
|
callback, &classic_read_remote_name_),
|
|
GetGdShimHandler());
|
|
return BTM_CMD_STARTED;
|
|
}
|
|
|
|
BtmStatus Btm::ReadLeRemoteDeviceName(const RawAddress& raw_address,
|
|
tBTM_CMPL_CB* callback) {
|
|
if (!CheckLeAclLink(raw_address)) {
|
|
return BTM_UNKNOWN_ADDR;
|
|
}
|
|
|
|
if (!le_read_remote_name_.Start(raw_address)) {
|
|
return BTM_BUSY;
|
|
}
|
|
|
|
LOG_INFO("UNIMPLEMENTED %s need access to GATT module", __func__);
|
|
return BTM_UNKNOWN_ADDR;
|
|
}
|
|
|
|
BtmStatus Btm::CancelAllReadRemoteDeviceName() {
|
|
if (classic_read_remote_name_.IsInProgress() ||
|
|
le_read_remote_name_.IsInProgress()) {
|
|
if (classic_read_remote_name_.IsInProgress()) {
|
|
hci::Address address;
|
|
hci::Address::FromString(classic_read_remote_name_.AddressString(),
|
|
address);
|
|
|
|
GetName()->CancelRemoteNameRequest(
|
|
address,
|
|
common::BindOnce(
|
|
[](ReadRemoteName* classic_read_remote_name,
|
|
hci::ErrorCode status,
|
|
hci::Address address) { classic_read_remote_name->Stop(); },
|
|
&classic_read_remote_name_),
|
|
GetGdShimHandler());
|
|
}
|
|
if (le_read_remote_name_.IsInProgress()) {
|
|
LOG_INFO("UNIMPLEMENTED %s need access to GATT module", __func__);
|
|
}
|
|
return BTM_UNKNOWN_ADDR;
|
|
}
|
|
LOG_WARN("%s Cancelling classic remote device name without one in progress",
|
|
__func__);
|
|
return BTM_WRONG_MODE;
|
|
}
|
|
|
|
void Btm::StartAdvertising() {
|
|
if (advertiser_id_ == hci::LeAdvertisingManager::kInvalidId) {
|
|
LOG_WARN("%s Already advertising; please stop prior to starting again",
|
|
__func__);
|
|
return;
|
|
}
|
|
|
|
hci::ExtendedAdvertisingConfig config = {};
|
|
advertiser_id_ = GetAdvertising()->ExtendedCreateAdvertiser(
|
|
0x00, config,
|
|
common::Bind([](hci::Address, hci::AddressType) { /*OnScan*/ }),
|
|
common::Bind([](hci::ErrorCode, uint8_t, uint8_t) { /*OnTerminated*/ }),
|
|
0, 0, GetGdShimHandler());
|
|
if (advertiser_id_ == hci::LeAdvertisingManager::kInvalidId) {
|
|
LOG_WARN("%s Unable to start advertising", __func__);
|
|
return;
|
|
}
|
|
LOG_INFO("%s Started advertising", __func__);
|
|
}
|
|
|
|
void Btm::StopAdvertising() {
|
|
if (advertiser_id_ == hci::LeAdvertisingManager::kInvalidId) {
|
|
LOG_WARN("%s No active advertising", __func__);
|
|
return;
|
|
}
|
|
GetAdvertising()->RemoveAdvertiser(advertiser_id_);
|
|
advertiser_id_ = hci::LeAdvertisingManager::kInvalidId;
|
|
LOG_INFO("%s Stopped advertising", __func__);
|
|
}
|
|
|
|
void Btm::StartConnectability() { StartAdvertising(); }
|
|
|
|
void Btm::StopConnectability() { StopAdvertising(); }
|
|
|
|
void Btm::StartActiveScanning() { StartScanning(kActiveScanning); }
|
|
|
|
void Btm::StopActiveScanning() { GetScanning()->Scan(false); }
|
|
|
|
void Btm::SetScanningTimer(uint64_t duration_ms,
|
|
common::OnceCallback<void()> callback) {
|
|
scanning_timer_.Schedule(std::move(callback),
|
|
std::chrono::milliseconds(duration_ms));
|
|
}
|
|
|
|
void Btm::CancelScanningTimer() { scanning_timer_.Cancel(); }
|
|
|
|
void Btm::StartObserving() { StartScanning(kPassiveScanning); }
|
|
|
|
void Btm::StopObserving() { StopActiveScanning(); }
|
|
|
|
void Btm::SetObservingTimer(uint64_t duration_ms,
|
|
common::OnceCallback<void()> callback) {
|
|
observing_timer_.Schedule(std::move(callback),
|
|
std::chrono::milliseconds(duration_ms));
|
|
}
|
|
|
|
void Btm::CancelObservingTimer() { observing_timer_.Cancel(); }
|
|
|
|
void Btm::StartScanning(bool use_active_scanning) {
|
|
GetScanning()->RegisterScanningCallback(&scanning_callbacks_);
|
|
GetScanning()->Scan(true);
|
|
}
|
|
|
|
size_t Btm::GetNumberOfAdvertisingInstances() const {
|
|
return GetAdvertising()->GetNumberOfAdvertisingInstances();
|
|
}
|
|
|
|
tBTM_STATUS Btm::CreateBond(const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type,
|
|
tBT_TRANSPORT transport, int device_type) {
|
|
if (transport == BT_TRANSPORT_UNKNOWN) {
|
|
if (device_type & BT_DEVICE_TYPE_BLE) {
|
|
transport = BT_TRANSPORT_LE;
|
|
} else if (device_type & BT_DEVICE_TYPE_BREDR) {
|
|
transport = BT_TRANSPORT_BR_EDR;
|
|
}
|
|
LOG_INFO("%s guessing transport as %02x ", __func__, transport);
|
|
}
|
|
|
|
auto security_manager = GetSecurityModule()->GetSecurityManager();
|
|
switch (transport) {
|
|
case BT_TRANSPORT_BR_EDR:
|
|
security_manager->CreateBond(ToAddressWithType(bd_addr, BLE_ADDR_PUBLIC));
|
|
break;
|
|
case BT_TRANSPORT_LE:
|
|
security_manager->CreateBondLe(ToAddressWithType(bd_addr, addr_type));
|
|
break;
|
|
default:
|
|
return BTM_ILLEGAL_VALUE;
|
|
}
|
|
return BTM_CMD_STARTED;
|
|
}
|
|
|
|
bool Btm::CancelBond(const RawAddress& bd_addr) {
|
|
auto security_manager = GetSecurityModule()->GetSecurityManager();
|
|
security_manager->CancelBond(ToAddressWithType(bd_addr, BLE_ADDR_PUBLIC));
|
|
return true;
|
|
}
|
|
|
|
bool Btm::RemoveBond(const RawAddress& bd_addr) {
|
|
// TODO(cmanton) Check if acl is connected
|
|
auto security_manager = GetSecurityModule()->GetSecurityManager();
|
|
security_manager->RemoveBond(ToAddressWithType(bd_addr, BLE_ADDR_PUBLIC));
|
|
return true;
|
|
}
|
|
|
|
uint16_t Btm::GetAclHandle(const RawAddress& remote_bda,
|
|
tBT_TRANSPORT transport) {
|
|
auto acl_manager = GetAclManager();
|
|
if (transport == BT_TRANSPORT_BR_EDR) {
|
|
return acl_manager->HACK_GetHandle(ToGdAddress(remote_bda));
|
|
} else {
|
|
return acl_manager->HACK_GetLeHandle(ToGdAddress(remote_bda));
|
|
}
|
|
}
|
|
|
|
hci::AddressWithType Btm::GetAddressAndType(const RawAddress& bd_addr) {
|
|
tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(bd_addr);
|
|
if (p_dev_rec != NULL && p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) {
|
|
if (!p_dev_rec->ble.identity_address_with_type.bda.IsEmpty()) {
|
|
return ToAddressWithType(p_dev_rec->ble.identity_address_with_type.bda,
|
|
p_dev_rec->ble.identity_address_with_type.type);
|
|
} else {
|
|
return ToAddressWithType(p_dev_rec->ble.pseudo_addr,
|
|
p_dev_rec->ble.ble_addr_type);
|
|
}
|
|
}
|
|
LOG(ERROR) << "Unknown bd_addr. Use public address";
|
|
return ToAddressWithType(bd_addr, BLE_ADDR_PUBLIC);
|
|
}
|
|
|
|
void Btm::Register_HACK_SetScoDisconnectCallback(
|
|
HACK_ScoDisconnectCallback callback) {
|
|
GetAclManager()->HACK_SetScoDisconnectCallback(callback);
|
|
}
|
|
|
|
} // namespace shim
|
|
|
|
} // namespace bluetooth
|