blob: 8eb884d9a6f54a757b6480aea7419d11adf66ff5 [file] [log] [blame]
/*
* 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 <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/shim.h"
#include "osi/include/log.h"
#include "stack/btm/btm_int_types.h"
#include "types/class_of_device.h"
#include "types/raw_address.h"
#include "hci/le_advertising_manager.h"
#include "hci/le_scanning_manager.h"
#include "main/shim/helpers.h"
#include "neighbor/connectability.h"
#include "neighbor/discoverability.h"
#include "neighbor/inquiry.h"
#include "neighbor/name.h"
#include "neighbor/page.h"
#include "security/security_module.h"
#include "shim/controller.h"
extern tBTM_CB btm_cb;
static constexpr size_t kRemoteDeviceNameLength = 248;
static constexpr uint8_t kAdvDataInfoNotPresent = 0xff;
static constexpr uint8_t kTxPowerInformationNotPresent = 0x7f;
static constexpr uint8_t kNotPeriodicAdvertisement = 0x00;
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,
uint8_t* 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);
void bluetooth::shim::Btm::StartUp(bluetooth::shim::Btm* btm) {
CHECK(btm != nullptr);
std::unique_lock<std::mutex> lock(btm->sync_mutex_);
CHECK(btm->observing_timer_ == nullptr);
CHECK(btm->scanning_timer_ == nullptr);
btm->observing_timer_ = new bluetooth::shim::Timer("observing_timer");
btm->scanning_timer_ = new bluetooth::shim::Timer("scanning_timer");
}
void bluetooth::shim::Btm::ShutDown(bluetooth::shim::Btm* btm) {
CHECK(btm != nullptr);
std::unique_lock<std::mutex> lock(btm->sync_mutex_);
CHECK(btm->observing_timer_ != nullptr);
CHECK(btm->scanning_timer_ != nullptr);
delete btm->scanning_timer_;
delete btm->observing_timer_;
btm->scanning_timer_ = nullptr;
btm->observing_timer_ = nullptr;
}
void bluetooth::shim::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_.cod, response.clock_offset_);
}
}
void bluetooth::shim::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_.cod, response.clock_offset_, response.rssi_);
}
}
void bluetooth::shim::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().cod, view.GetClockOffset(), view.GetRssi(), data,
data_len);
}
void bluetooth::shim::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;
}
bool bluetooth::shim::Btm::SetInquiryFilter(uint8_t mode, uint8_t type,
tBTM_INQ_FILT_COND data) {
switch (mode) {
case kInquiryModeOff:
break;
case kLimitedInquiryMode:
LOG_WARN("UNIMPLEMENTED %s", __func__);
break;
case kGeneralInquiryMode:
LOG_WARN("UNIMPLEMENTED %s", __func__);
break;
default:
LOG_WARN("%s Unknown inquiry mode:%d", __func__, mode);
return false;
}
return true;
}
void bluetooth::shim::Btm::SetFilterInquiryOnAddress() {
LOG_WARN("UNIMPLEMENTED %s", __func__);
}
void bluetooth::shim::Btm::SetFilterInquiryOnDevice() {
LOG_WARN("UNIMPLEMENTED %s", __func__);
}
void bluetooth::shim::Btm::ClearInquiryFilter() {
LOG_WARN("UNIMPLEMENTED %s", __func__);
}
void bluetooth::shim::Btm::SetStandardInquiryResultMode() {
bluetooth::shim::GetInquiry()->SetStandardInquiryResultMode();
}
void bluetooth::shim::Btm::SetInquiryWithRssiResultMode() {
bluetooth::shim::GetInquiry()->SetInquiryWithRssiResultMode();
}
void bluetooth::shim::Btm::SetExtendedInquiryResultMode() {
bluetooth::shim::GetInquiry()->SetExtendedInquiryResultMode();
}
void bluetooth::shim::Btm::SetInterlacedInquiryScan() {
bluetooth::shim::GetInquiry()->SetInterlacedScan();
}
void bluetooth::shim::Btm::SetStandardInquiryScan() {
bluetooth::shim::GetInquiry()->SetStandardScan();
}
bool bluetooth::shim::Btm::IsInterlacedScanSupported() const {
return controller_get_interface()->supports_interlaced_inquiry_scan();
}
/**
* One shot inquiry
*/
bool bluetooth::shim::Btm::StartInquiry(
uint8_t mode, uint8_t duration, uint8_t max_responses,
LegacyInquiryCompleteCallback legacy_inquiry_complete_callback) {
switch (mode) {
case kInquiryModeOff:
LOG_DEBUG("%s Stopping inquiry mode", __func__);
if (limited_inquiry_active_ || general_inquiry_active_) {
bluetooth::shim::GetInquiry()->StopInquiry();
limited_inquiry_active_ = false;
general_inquiry_active_ = false;
}
active_inquiry_mode_ = kInquiryModeOff;
break;
case kLimitedInquiryMode:
case kGeneralInquiryMode: {
if (mode == kLimitedInquiryMode) {
LOG_DEBUG(
"%s Starting limited inquiry mode duration:%hhd max responses:%hhd",
__func__, duration, max_responses);
limited_inquiry_active_ = true;
bluetooth::shim::GetInquiry()->StartLimitedInquiry(duration,
max_responses);
active_inquiry_mode_ = kLimitedInquiryMode;
} else {
LOG_DEBUG(
"%s Starting general inquiry mode duration:%hhd max responses:%hhd",
__func__, duration, max_responses);
general_inquiry_active_ = true;
bluetooth::shim::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 bluetooth::shim::Btm::CancelInquiry() {
LOG_DEBUG("%s", __func__);
if (limited_inquiry_active_ || general_inquiry_active_) {
bluetooth::shim::GetInquiry()->StopInquiry();
limited_inquiry_active_ = false;
general_inquiry_active_ = false;
}
}
bool bluetooth::shim::Btm::IsInquiryActive() const {
return IsGeneralInquiryActive() || IsLimitedInquiryActive();
}
bool bluetooth::shim::Btm::IsGeneralInquiryActive() const {
return general_inquiry_active_;
}
bool bluetooth::shim::Btm::IsLimitedInquiryActive() const {
return limited_inquiry_active_;
}
/**
* Periodic
*/
bool bluetooth::shim::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;
bluetooth::shim::GetInquiry()->StopPeriodicInquiry();
break;
case kLimitedInquiryMode:
case kGeneralInquiryMode: {
if (mode == kLimitedInquiryMode) {
LOG_DEBUG("%s Starting limited periodic inquiry mode", __func__);
limited_periodic_inquiry_active_ = true;
bluetooth::shim::GetInquiry()->StartLimitedPeriodicInquiry(
duration, max_responses, max_delay, min_delay);
} else {
LOG_DEBUG("%s Starting general periodic inquiry mode", __func__);
general_periodic_inquiry_active_ = true;
bluetooth::shim::GetInquiry()->StartGeneralPeriodicInquiry(
duration, max_responses, max_delay, min_delay);
}
} break;
default:
LOG_WARN("%s Unknown inquiry mode:%d", __func__, mode);
return false;
}
return true;
}
void bluetooth::shim::Btm::CancelPeriodicInquiry() {
limited_periodic_inquiry_active_ = false;
general_periodic_inquiry_active_ = false;
bluetooth::shim::GetInquiry()->StopPeriodicInquiry();
}
bool bluetooth::shim::Btm::IsGeneralPeriodicInquiryActive() const {
return general_periodic_inquiry_active_;
}
bool bluetooth::shim::Btm::IsLimitedPeriodicInquiryActive() const {
return limited_periodic_inquiry_active_;
}
/**
* Discoverability
*/
void bluetooth::shim::Btm::RegisterInquiryCallbacks() {
bluetooth::neighbor::InquiryCallbacks inquiry_callbacks;
inquiry_callbacks.result =
std::bind(&Btm::OnInquiryResult, this, std::placeholders::_1);
inquiry_callbacks.result_with_rssi =
std::bind(&Btm::OnInquiryResultWithRssi, this, std::placeholders::_1);
inquiry_callbacks.extended_result =
std::bind(&Btm::OnExtendedInquiryResult, this, std::placeholders::_1);
inquiry_callbacks.complete =
std::bind(&Btm::OnInquiryComplete, this, std::placeholders::_1);
bluetooth::shim::GetInquiry()->RegisterCallbacks(inquiry_callbacks);
}
bluetooth::neighbor::ScanParameters params_{
.interval = 0,
.window = 0,
};
void bluetooth::shim::Btm::SetClassicGeneralDiscoverability(uint16_t window,
uint16_t interval) {
params_.window = window;
params_.interval = interval;
bluetooth::shim::GetInquiry()->SetScanActivity(params_);
bluetooth::shim::GetDiscoverability()->StartGeneralDiscoverability();
}
void bluetooth::shim::Btm::SetClassicLimitedDiscoverability(uint16_t window,
uint16_t interval) {
params_.window = window;
params_.interval = interval;
bluetooth::shim::GetInquiry()->SetScanActivity(params_);
bluetooth::shim::GetDiscoverability()->StartLimitedDiscoverability();
}
void bluetooth::shim::Btm::SetClassicDiscoverabilityOff() {
bluetooth::shim::GetDiscoverability()->StopDiscoverability();
}
DiscoverabilityState bluetooth::shim::Btm::GetClassicDiscoverabilityState()
const {
DiscoverabilityState state{.mode = BTM_NON_DISCOVERABLE,
.interval = params_.interval,
.window = params_.window};
if (bluetooth::shim::GetDiscoverability()
->IsGeneralDiscoverabilityEnabled()) {
state.mode = BTM_GENERAL_DISCOVERABLE;
} else if (bluetooth::shim::GetDiscoverability()
->IsLimitedDiscoverabilityEnabled()) {
state.mode = BTM_LIMITED_DISCOVERABLE;
}
return state;
}
void bluetooth::shim::Btm::SetLeGeneralDiscoverability() {
LOG_WARN("UNIMPLEMENTED %s", __func__);
}
void bluetooth::shim::Btm::SetLeLimitedDiscoverability() {
LOG_WARN("UNIMPLEMENTED %s", __func__);
}
void bluetooth::shim::Btm::SetLeDiscoverabilityOff() {
LOG_WARN("UNIMPLEMENTED %s", __func__);
}
DiscoverabilityState bluetooth::shim::Btm::GetLeDiscoverabilityState() const {
DiscoverabilityState state{
.mode = kDiscoverableModeOff,
.interval = 0,
.window = 0,
};
LOG_WARN("UNIMPLEMENTED %s", __func__);
return state;
}
/**
* Connectability
*/
void bluetooth::shim::Btm::SetClassicConnectibleOn() {
bluetooth::shim::GetConnectability()->StartConnectability();
}
void bluetooth::shim::Btm::SetClassicConnectibleOff() {
bluetooth::shim::GetConnectability()->StopConnectability();
}
ConnectabilityState bluetooth::shim::Btm::GetClassicConnectabilityState()
const {
ConnectabilityState state{.interval = params_.interval,
.window = params_.window};
if (bluetooth::shim::GetConnectability()->IsConnectable()) {
state.mode = BTM_CONNECTABLE;
} else {
state.mode = BTM_NON_CONNECTABLE;
}
return state;
}
void bluetooth::shim::Btm::SetInterlacedPageScan() {
bluetooth::shim::GetPage()->SetInterlacedScan();
}
void bluetooth::shim::Btm::SetStandardPageScan() {
bluetooth::shim::GetPage()->SetStandardScan();
}
void bluetooth::shim::Btm::SetLeConnectibleOn() {
LOG_WARN("UNIMPLEMENTED %s", __func__);
}
void bluetooth::shim::Btm::SetLeConnectibleOff() {
LOG_WARN("UNIMPLEMENTED %s", __func__);
}
ConnectabilityState bluetooth::shim::Btm::GetLeConnectabilityState() const {
ConnectabilityState state{
.mode = kConnectibleModeOff,
.interval = 0,
.window = 0,
};
LOG_WARN("UNIMPLEMENTED %s", __func__);
return state;
}
bool bluetooth::shim::Btm::IsLeAclConnected(
const RawAddress& raw_address) const {
// TODO(cmanton) Check current acl's for this address and indicate if there is
// an LE option. For now ignore and default to classic.
LOG_INFO("%s Le acl connection check is temporarily unsupported", __func__);
return false;
}
bluetooth::shim::BtmStatus bluetooth::shim::Btm::ReadClassicRemoteDeviceName(
const RawAddress& raw_address, tBTM_CMPL_CB* callback) {
if (!CheckClassicAclLink(raw_address)) {
return bluetooth::shim::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 bluetooth::shim::BTM_BUSY;
}
LOG_DEBUG("%s Start read name from address:%s", __func__,
raw_address.ToString().c_str());
bluetooth::shim::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_DEBUG("%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_),
bluetooth::shim::GetGdShimHandler());
return bluetooth::shim::BTM_CMD_STARTED;
}
bluetooth::shim::BtmStatus bluetooth::shim::Btm::ReadLeRemoteDeviceName(
const RawAddress& raw_address, tBTM_CMPL_CB* callback) {
if (!CheckLeAclLink(raw_address)) {
return bluetooth::shim::BTM_UNKNOWN_ADDR;
}
if (!le_read_remote_name_.Start(raw_address)) {
return bluetooth::shim::BTM_BUSY;
}
LOG_INFO("UNIMPLEMENTED %s need access to GATT module", __func__);
return bluetooth::shim::BTM_UNKNOWN_ADDR;
}
bluetooth::shim::BtmStatus
bluetooth::shim::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);
bluetooth::shim::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_),
bluetooth::shim::GetGdShimHandler());
}
if (le_read_remote_name_.IsInProgress()) {
LOG_INFO("UNIMPLEMENTED %s need access to GATT module", __func__);
}
return bluetooth::shim::BTM_UNKNOWN_ADDR;
}
LOG_WARN("%s Cancelling classic remote device name without one in progress",
__func__);
return bluetooth::shim::BTM_WRONG_MODE;
}
void bluetooth::shim::Btm::StartAdvertising() {
if (advertiser_id_ == hci::LeAdvertisingManager::kInvalidId) {
LOG_WARN("%s Already advertising; please stop prior to starting again",
__func__);
return;
}
hci::AdvertisingConfig config;
advertiser_id_ = bluetooth::shim::GetAdvertising()->CreateAdvertiser(
config, common::Bind([](hci::Address, hci::AddressType) { /*OnScan*/ }),
common::Bind([](hci::ErrorCode, uint8_t, uint8_t) { /*OnTerminated*/ }),
bluetooth::shim::GetGdShimHandler());
if (advertiser_id_ == hci::LeAdvertisingManager::kInvalidId) {
LOG_WARN("%s Unable to start advertising", __func__);
return;
}
LOG_DEBUG("%s Started advertising", __func__);
}
void bluetooth::shim::Btm::StopAdvertising() {
if (advertiser_id_ == hci::LeAdvertisingManager::kInvalidId) {
LOG_WARN("%s No active advertising", __func__);
return;
}
bluetooth::shim::GetAdvertising()->RemoveAdvertiser(advertiser_id_);
advertiser_id_ = hci::LeAdvertisingManager::kInvalidId;
LOG_DEBUG("%s Stopped advertising", __func__);
}
void bluetooth::shim::Btm::StartConnectability() { StartAdvertising(); }
void bluetooth::shim::Btm::StopConnectability() { StopAdvertising(); }
void bluetooth::shim::Btm::StartActiveScanning() {
StartScanning(kActiveScanning);
}
void bluetooth::shim::Btm::StopActiveScanning() {
bluetooth::shim::GetScanning()->StopScan(base::Bind([]() {}));
}
void bluetooth::shim::Btm::SetScanningTimer(uint64_t duration_ms,
std::function<void()> func) {
scanning_timer_->Set(duration_ms, func);
}
void bluetooth::shim::Btm::CancelScanningTimer() { scanning_timer_->Cancel(); }
void bluetooth::shim::Btm::StartObserving() { StartScanning(kPassiveScanning); }
void bluetooth::shim::Btm::StopObserving() { StopActiveScanning(); }
void bluetooth::shim::Btm::SetObservingTimer(uint64_t duration_ms,
std::function<void()> func) {
observing_timer_->Set(duration_ms, func);
}
void bluetooth::shim::Btm::CancelObservingTimer() {
observing_timer_->Cancel();
}
namespace bluetooth {
namespace hci {
constexpr int kAdvertisingReportBufferSize = 1024;
struct ExtendedEventTypeOptions {
bool connectable{false};
bool scannable{false};
bool directed{false};
bool scan_response{false};
bool legacy{false};
bool continuing{false};
bool truncated{false};
};
constexpr uint16_t kBleEventConnectableBit =
(0x0001 << 0); // BLE_EVT_CONNECTABLE_BIT
constexpr uint16_t kBleEventScannableBit =
(0x0001 << 1); // BLE_EVT_SCANNABLE_BIT
constexpr uint16_t kBleEventDirectedBit =
(0x0001 << 2); // BLE_EVT_DIRECTED_BIT
constexpr uint16_t kBleEventScanResponseBit =
(0x0001 << 3); // BLE_EVT_SCAN_RESPONSE_BIT
constexpr uint16_t kBleEventLegacyBit = (0x0001 << 4); // BLE_EVT_LEGACY_BIT
constexpr uint16_t kBleEventIncompleteContinuing = (0x0001 << 5);
constexpr uint16_t kBleEventIncompleteTruncated = (0x0001 << 6);
static void TransformToExtendedEventType(uint16_t* extended_event_type,
ExtendedEventTypeOptions o) {
ASSERT(extended_event_type != nullptr);
*extended_event_type = (o.connectable ? kBleEventConnectableBit : 0) |
(o.scannable ? kBleEventScannableBit : 0) |
(o.directed ? kBleEventDirectedBit : 0) |
(o.scan_response ? kBleEventScanResponseBit : 0) |
(o.legacy ? kBleEventLegacyBit : 0) |
(o.continuing ? kBleEventIncompleteContinuing : 0) |
(o.truncated ? kBleEventIncompleteTruncated : 0);
}
class BtmScanningCallbacks : public bluetooth::hci::LeScanningManagerCallbacks {
public:
virtual void on_advertisements(
std::vector<std::shared_ptr<LeReport>> reports) {
for (auto le_report : reports) {
uint8_t address_type = static_cast<uint8_t>(le_report->address_type_);
uint16_t extended_event_type = 0;
uint8_t* report_data = nullptr;
size_t report_len = 0;
uint8_t advertising_data_buffer[kAdvertisingReportBufferSize];
// Copy gap data, if any, into temporary buffer as payload for legacy
// stack.
if (!le_report->gap_data_.empty()) {
bzero(advertising_data_buffer, kAdvertisingReportBufferSize);
uint8_t* p = advertising_data_buffer;
for (auto gap_data : le_report->gap_data_) {
*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();
}
report_data = advertising_data_buffer;
report_len = p - report_data;
}
switch (le_report->GetReportType()) {
case hci::LeReport::ReportType::ADVERTISING_EVENT: {
switch (le_report->advertising_event_type_) {
case hci::AdvertisingEventType::ADV_IND:
TransformToExtendedEventType(
&extended_event_type,
{.connectable = true, .scannable = true, .legacy = true});
break;
case hci::AdvertisingEventType::ADV_DIRECT_IND:
TransformToExtendedEventType(
&extended_event_type,
{.connectable = true, .directed = true, .legacy = true});
break;
case hci::AdvertisingEventType::ADV_SCAN_IND:
TransformToExtendedEventType(&extended_event_type,
{.scannable = true, .legacy = true});
break;
case hci::AdvertisingEventType::ADV_NONCONN_IND:
TransformToExtendedEventType(&extended_event_type,
{.legacy = true});
break;
case hci::AdvertisingEventType::
ADV_DIRECT_IND_LOW: // SCAN_RESPONSE
TransformToExtendedEventType(&extended_event_type,
{.connectable = true,
.scannable = true,
.scan_response = true,
.legacy = true});
break;
default:
LOG_WARN(
"%s Unsupported event type:%s", __func__,
AdvertisingEventTypeText(le_report->advertising_event_type_)
.c_str());
return;
}
RawAddress raw_address = ToRawAddress(le_report->address_);
btm_ble_process_adv_addr(raw_address, &address_type);
btm_ble_process_adv_pkt_cont(
extended_event_type, address_type, raw_address,
kPhyConnectionLe1M, kPhyConnectionNone, kAdvDataInfoNotPresent,
kTxPowerInformationNotPresent, le_report->rssi_,
kNotPeriodicAdvertisement, report_len, report_data);
} break;
case hci::LeReport::ReportType::DIRECTED_ADVERTISING_EVENT:
LOG_WARN("%s Directed advertising is unsupported from device:%s",
__func__, le_report->address_.ToString().c_str());
break;
case hci::LeReport::ReportType::EXTENDED_ADVERTISING_EVENT: {
std::shared_ptr<hci::ExtendedLeReport> extended_le_report =
std::static_pointer_cast<hci::ExtendedLeReport>(le_report);
TransformToExtendedEventType(
&extended_event_type,
{.connectable = extended_le_report->connectable_,
.scannable = extended_le_report->scannable_,
.directed = extended_le_report->directed_,
.scan_response = extended_le_report->scan_response_,
.legacy = false,
.continuing = !extended_le_report->complete_,
.truncated = extended_le_report->truncated_});
RawAddress raw_address = ToRawAddress(le_report->address_);
if (address_type != BLE_ADDR_ANONYMOUS) {
btm_ble_process_adv_addr(raw_address, &address_type);
}
btm_ble_process_adv_pkt_cont(
extended_event_type, address_type, raw_address,
kPhyConnectionLe1M, kPhyConnectionNone, kAdvDataInfoNotPresent,
kTxPowerInformationNotPresent, le_report->rssi_,
kNotPeriodicAdvertisement, report_len, report_data);
} break;
}
}
}
virtual void on_timeout() { LOG_WARN("%s Scanning timeout", __func__); }
os::Handler* Handler() { return bluetooth::shim::GetGdShimHandler(); }
};
} // namespace hci
} // namespace bluetooth
bluetooth::hci::BtmScanningCallbacks btm_scanning_callbacks;
void bluetooth::shim::Btm::StartScanning(bool use_active_scanning) {
bluetooth::shim::GetScanning()->StartScan(&btm_scanning_callbacks);
}
size_t bluetooth::shim::Btm::GetNumberOfAdvertisingInstances() const {
return bluetooth::shim::GetAdvertising()->GetNumberOfAdvertisingInstances();
}
tBTM_STATUS bluetooth::shim::Btm::CreateBond(const RawAddress& bd_addr,
tBLE_ADDR_TYPE addr_type,
tBT_TRANSPORT transport,
int device_type) {
if (transport == BTA_TRANSPORT_UNKNOWN) {
if (device_type & BT_DEVICE_TYPE_BLE) {
transport = BTA_TRANSPORT_LE;
} else if (device_type & BT_DEVICE_TYPE_BREDR) {
transport = BTA_TRANSPORT_BR_EDR;
}
LOG_DEBUG("%s guessing transport as %02x ", __func__, transport);
}
auto security_manager =
bluetooth::shim::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 bluetooth::shim::BTM_ILLEGAL_VALUE;
}
return bluetooth::shim::BTM_SUCCESS;
}
bool bluetooth::shim::Btm::CancelBond(const RawAddress& bd_addr) {
auto security_manager =
bluetooth::shim::GetSecurityModule()->GetSecurityManager();
security_manager->CancelBond(ToAddressWithType(bd_addr, BLE_ADDR_PUBLIC));
return true;
}
bool bluetooth::shim::Btm::RemoveBond(const RawAddress& bd_addr) {
// TODO(cmanton) Check if acl is connected
auto security_manager =
bluetooth::shim::GetSecurityModule()->GetSecurityManager();
security_manager->RemoveBond(ToAddressWithType(bd_addr, BLE_ADDR_PUBLIC));
return true;
}