blob: 526983298c5cc0b09d68947db5ea940e3573a17a [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 "main/shim/btm.h"
#include <base/logging.h>
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <mutex>
#include "hci/acl_manager.h"
#include "hci/controller_interface.h"
#include "hci/le_advertising_manager.h"
#include "hci/le_scanning_manager.h"
#include "main/shim/entry.h"
#include "main/shim/helpers.h"
#include "neighbor/connectability.h"
#include "neighbor/discoverability.h"
#include "neighbor/inquiry.h"
#include "neighbor/page.h"
#include "stack/btm/btm_dev.h"
#include "stack/btm/btm_int_types.h"
#include "types/ble_address_with_type.h"
#include "types/bt_transport.h"
#include "types/raw_address.h"
extern tBTM_CB btm_cb;
static constexpr bool kActiveScanning = true;
static constexpr bool kPassiveScanning = false;
using BtmRemoteDeviceName = tBTM_REMOTE_DEV_NAME;
void btm_ble_process_adv_addr(RawAddress& raw_address,
tBLE_ADDR_TYPE* address_type);
void btm_ble_process_adv_pkt_cont(uint16_t event_type,
tBLE_ADDR_TYPE 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, const uint8_t* data,
const RawAddress& original_bda);
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::OnSetScannerParameterComplete(
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 = to_ble_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);
}
// Pass up to GattService#onScanResult
RawAddress original_bda = raw_address;
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.data(), original_bda);
}
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 */){};
void Btm::ScanningCallbacks::OnPeriodicSyncStarted(
int /* reg_id */, uint8_t /* status */, uint16_t /* sync_handle */,
uint8_t /* advertising_sid */,
bluetooth::hci::AddressWithType /* address_with_type */, uint8_t /* phy */,
uint16_t /* interval */) {}
void Btm::ScanningCallbacks::OnPeriodicSyncReport(
uint16_t /* sync_handle */, int8_t /* tx_power */, int8_t /* rssi */,
uint8_t /* status */, std::vector<uint8_t> /* data */) {}
void Btm::ScanningCallbacks::OnPeriodicSyncLost(uint16_t /* sync_handle */) {}
void Btm::ScanningCallbacks::OnPeriodicSyncTransferred(
int /* pa_source */, uint8_t /* status */,
bluetooth::hci::Address /* address */) {}
void Btm::ScanningCallbacks::OnBigInfoReport(uint16_t /* sync_handle */,
bool /* encrypted */) {}
Btm::Btm(os::Handler* handler, neighbor::InquiryModule* inquiry)
: scanning_timer_(handler), observing_timer_(handler) {
ASSERT(handler != nullptr);
ASSERT(inquiry != nullptr);
}
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 bluetooth::shim::GetController()->SupportsInterlacedInquiryScan();
}
/**
* 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_NAME_CMPL_CB* /* callback */) {
LOG_ALWAYS_FATAL("unreachable");
return BTM_UNDEFINED;
}
BtmStatus Btm::CancelAllReadRemoteDeviceName() {
LOG_ALWAYS_FATAL("unreachable");
return BTM_UNDEFINED;
}
void Btm::StartAdvertising() { LOG_ALWAYS_FATAL("unreachable"); }
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();
}
size_t Btm::GetNumberOfAdvertisingInstancesInUse() const {
return GetAdvertising()->GetNumberOfAdvertisingInstancesInUse();
}
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.AddressType());
}
}
LOG(ERROR) << "Unknown bd_addr. Use public address";
return ToAddressWithType(bd_addr, BLE_ADDR_PUBLIC);
}
} // namespace shim
} // namespace bluetooth