blob: 9508725f2e256b362a06839ba3092a9d6db46368 [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_gd_neigh"
#include "neighbor/scan.h"
#include <memory>
#include "hci/hci_layer.h"
#include "hci/hci_packets.h"
#include "module.h"
#include "os/handler.h"
#include "os/log.h"
namespace bluetooth {
namespace neighbor {
struct ScanModule::impl {
impl(ScanModule& module);
void SetInquiryScan(bool enabled);
bool IsInquiryEnabled() const;
void SetPageScan(bool enabled);
bool IsPageEnabled() const;
void Start();
void Stop();
private:
ScanModule& module_;
bool inquiry_scan_enabled_;
bool page_scan_enabled_;
void WriteScanEnable();
void ReadScanEnable(hci::ScanEnable);
void OnCommandComplete(hci::CommandCompleteView status);
hci::HciLayer* hci_layer_;
os::Handler* handler_;
};
const ModuleFactory neighbor::ScanModule::Factory = ModuleFactory([]() { return new neighbor::ScanModule(); });
neighbor::ScanModule::impl::impl(neighbor::ScanModule& module)
: module_(module), inquiry_scan_enabled_(false), page_scan_enabled_(false) {}
void neighbor::ScanModule::impl::OnCommandComplete(hci::CommandCompleteView view) {
switch (view.GetCommandOpCode()) {
case hci::OpCode::READ_SCAN_ENABLE: {
auto packet = hci::ReadScanEnableCompleteView::Create(view);
ASSERT(packet.IsValid());
ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
ReadScanEnable(packet.GetScanEnable());
} break;
case hci::OpCode::WRITE_SCAN_ENABLE: {
auto packet = hci::WriteScanEnableCompleteView::Create(view);
ASSERT(packet.IsValid());
ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
} break;
default:
LOG_ERROR("Unhandled command %s", hci::OpCodeText(view.GetCommandOpCode()).c_str());
break;
}
}
void neighbor::ScanModule::impl::WriteScanEnable() {
hci::ScanEnable scan_enable;
if (inquiry_scan_enabled_ && !page_scan_enabled_) {
scan_enable = hci::ScanEnable::INQUIRY_SCAN_ONLY;
} else if (!inquiry_scan_enabled_ && page_scan_enabled_) {
scan_enable = hci::ScanEnable::PAGE_SCAN_ONLY;
} else if (inquiry_scan_enabled_ && page_scan_enabled_) {
scan_enable = hci::ScanEnable::INQUIRY_AND_PAGE_SCAN;
} else {
scan_enable = hci::ScanEnable::NO_SCANS;
}
{
std::unique_ptr<hci::WriteScanEnableBuilder> packet = hci::WriteScanEnableBuilder::Create(scan_enable);
hci_layer_->EnqueueCommand(std::move(packet), handler_->BindOnceOn(this, &impl::OnCommandComplete));
}
{
std::unique_ptr<hci::ReadScanEnableBuilder> packet = hci::ReadScanEnableBuilder::Create();
hci_layer_->EnqueueCommand(std::move(packet), handler_->BindOnceOn(this, &impl::OnCommandComplete));
}
}
void neighbor::ScanModule::impl::ReadScanEnable(hci::ScanEnable scan_enable) {
switch (scan_enable) {
case hci::ScanEnable::INQUIRY_SCAN_ONLY:
inquiry_scan_enabled_ = true;
page_scan_enabled_ = false;
break;
case hci::ScanEnable::PAGE_SCAN_ONLY:
inquiry_scan_enabled_ = false;
page_scan_enabled_ = true;
break;
case hci::ScanEnable::INQUIRY_AND_PAGE_SCAN:
inquiry_scan_enabled_ = true;
page_scan_enabled_ = true;
break;
default:
inquiry_scan_enabled_ = false;
page_scan_enabled_ = false;
break;
}
}
void neighbor::ScanModule::impl::SetInquiryScan(bool enabled) {
inquiry_scan_enabled_ = enabled;
WriteScanEnable();
}
void neighbor::ScanModule::impl::SetPageScan(bool enabled) {
page_scan_enabled_ = enabled;
WriteScanEnable();
}
bool neighbor::ScanModule::impl::IsInquiryEnabled() const {
return inquiry_scan_enabled_;
}
bool neighbor::ScanModule::impl::IsPageEnabled() const {
return page_scan_enabled_;
}
void neighbor::ScanModule::impl::Start() {
hci_layer_ = module_.GetDependency<hci::HciLayer>();
handler_ = module_.GetHandler();
std::unique_ptr<hci::ReadScanEnableBuilder> packet = hci::ReadScanEnableBuilder::Create();
hci_layer_->EnqueueCommand(std::move(packet), handler_->BindOnceOn(this, &impl::OnCommandComplete));
}
void neighbor::ScanModule::impl::Stop() {
LOG_INFO("inquiry scan enabled:%d page scan enabled:%d", inquiry_scan_enabled_, page_scan_enabled_);
}
neighbor::ScanModule::ScanModule() : pimpl_(std::make_unique<impl>(*this)) {}
neighbor::ScanModule::~ScanModule() {
pimpl_.reset();
}
void neighbor::ScanModule::SetInquiryScan() {
pimpl_->SetInquiryScan(true);
}
void neighbor::ScanModule::ClearInquiryScan() {
pimpl_->SetInquiryScan(false);
}
void neighbor::ScanModule::SetPageScan() {
pimpl_->SetPageScan(true);
}
void neighbor::ScanModule::ClearPageScan() {
pimpl_->SetPageScan(false);
}
bool neighbor::ScanModule::IsInquiryEnabled() const {
return pimpl_->IsInquiryEnabled();
}
bool neighbor::ScanModule::IsPageEnabled() const {
return pimpl_->IsPageEnabled();
}
void neighbor::ScanModule::ListDependencies(ModuleList* list) const {
list->add<hci::HciLayer>();
}
void neighbor::ScanModule::Start() {
pimpl_->Start();
}
void neighbor::ScanModule::Stop() {
pimpl_->Stop();
}
} // namespace neighbor
} // namespace bluetooth