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.
504 lines
18 KiB
504 lines
18 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_gd_neigh"
|
|
|
|
#include "neighbor/inquiry.h"
|
|
|
|
#include <memory>
|
|
|
|
#include "common/bind.h"
|
|
#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 {
|
|
|
|
static constexpr uint8_t kGeneralInquiryAccessCode = 0x33;
|
|
static constexpr uint8_t kLimitedInquiryAccessCode = 0x00;
|
|
|
|
struct InquiryModule::impl {
|
|
void RegisterCallbacks(InquiryCallbacks inquiry_callbacks);
|
|
void UnregisterCallbacks();
|
|
|
|
void StartOneShotInquiry(bool limited, InquiryLength inquiry_length, NumResponses num_responses);
|
|
void StopOneShotInquiry();
|
|
|
|
void StartPeriodicInquiry(
|
|
bool limited,
|
|
InquiryLength inquiry_length,
|
|
NumResponses num_responses,
|
|
PeriodLength max_delay,
|
|
PeriodLength min_delay);
|
|
void StopPeriodicInquiry();
|
|
|
|
void SetScanActivity(ScanParameters params);
|
|
|
|
void SetScanType(hci::InquiryScanType scan_type);
|
|
|
|
void SetInquiryMode(hci::InquiryMode mode);
|
|
|
|
void Start();
|
|
void Stop();
|
|
|
|
bool HasCallbacks() const;
|
|
|
|
impl(InquiryModule& inquiry_module);
|
|
|
|
private:
|
|
InquiryCallbacks inquiry_callbacks_;
|
|
|
|
InquiryModule& module_;
|
|
|
|
bool active_general_one_shot_{false};
|
|
bool active_limited_one_shot_{false};
|
|
bool active_general_periodic_{false};
|
|
bool active_limited_periodic_{false};
|
|
|
|
ScanParameters inquiry_scan_;
|
|
hci::InquiryMode inquiry_mode_;
|
|
hci::InquiryScanType inquiry_scan_type_;
|
|
int8_t inquiry_response_tx_power_;
|
|
|
|
bool IsInquiryActive() const;
|
|
|
|
void EnqueueCommandComplete(std::unique_ptr<hci::CommandBuilder> command);
|
|
void EnqueueCommandStatus(std::unique_ptr<hci::CommandBuilder> command);
|
|
void OnCommandComplete(hci::CommandCompleteView view);
|
|
void OnCommandStatus(hci::CommandStatusView status);
|
|
|
|
void EnqueueCommandCompleteSync(std::unique_ptr<hci::CommandBuilder> command);
|
|
void OnCommandCompleteSync(hci::CommandCompleteView view);
|
|
|
|
void OnEvent(hci::EventView view);
|
|
|
|
std::promise<void>* command_sync_{nullptr};
|
|
|
|
hci::HciLayer* hci_layer_;
|
|
os::Handler* handler_;
|
|
};
|
|
|
|
const ModuleFactory neighbor::InquiryModule::Factory = ModuleFactory([]() { return new neighbor::InquiryModule(); });
|
|
|
|
neighbor::InquiryModule::impl::impl(neighbor::InquiryModule& module) : module_(module) {}
|
|
|
|
void neighbor::InquiryModule::impl::OnCommandCompleteSync(hci::CommandCompleteView view) {
|
|
OnCommandComplete(view);
|
|
ASSERT(command_sync_ != nullptr);
|
|
command_sync_->set_value();
|
|
}
|
|
|
|
void neighbor::InquiryModule::impl::OnCommandComplete(hci::CommandCompleteView view) {
|
|
switch (view.GetCommandOpCode()) {
|
|
case hci::OpCode::INQUIRY_CANCEL: {
|
|
auto packet = hci::InquiryCancelCompleteView::Create(view);
|
|
ASSERT(packet.IsValid());
|
|
ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
|
|
} break;
|
|
|
|
case hci::OpCode::PERIODIC_INQUIRY_MODE: {
|
|
auto packet = hci::PeriodicInquiryModeCompleteView::Create(view);
|
|
ASSERT(packet.IsValid());
|
|
ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
|
|
} break;
|
|
|
|
case hci::OpCode::EXIT_PERIODIC_INQUIRY_MODE: {
|
|
auto packet = hci::ExitPeriodicInquiryModeCompleteView::Create(view);
|
|
ASSERT(packet.IsValid());
|
|
ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
|
|
} break;
|
|
|
|
case hci::OpCode::WRITE_INQUIRY_MODE: {
|
|
auto packet = hci::WriteInquiryModeCompleteView::Create(view);
|
|
ASSERT(packet.IsValid());
|
|
ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
|
|
} break;
|
|
|
|
case hci::OpCode::READ_INQUIRY_MODE: {
|
|
auto packet = hci::ReadInquiryModeCompleteView::Create(view);
|
|
ASSERT(packet.IsValid());
|
|
ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
|
|
inquiry_mode_ = packet.GetInquiryMode();
|
|
} break;
|
|
|
|
case hci::OpCode::READ_INQUIRY_RESPONSE_TRANSMIT_POWER_LEVEL: {
|
|
auto packet = hci::ReadInquiryResponseTransmitPowerLevelCompleteView::Create(view);
|
|
ASSERT(packet.IsValid());
|
|
ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
|
|
inquiry_response_tx_power_ = packet.GetTxPower();
|
|
} break;
|
|
|
|
case hci::OpCode::WRITE_INQUIRY_SCAN_ACTIVITY: {
|
|
auto packet = hci::WriteInquiryScanActivityCompleteView::Create(view);
|
|
ASSERT(packet.IsValid());
|
|
ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
|
|
} break;
|
|
|
|
case hci::OpCode::READ_INQUIRY_SCAN_ACTIVITY: {
|
|
auto packet = hci::ReadInquiryScanActivityCompleteView::Create(view);
|
|
ASSERT(packet.IsValid());
|
|
ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
|
|
inquiry_scan_.interval = packet.GetInquiryScanInterval();
|
|
inquiry_scan_.window = packet.GetInquiryScanWindow();
|
|
} break;
|
|
|
|
case hci::OpCode::WRITE_INQUIRY_SCAN_TYPE: {
|
|
auto packet = hci::WriteInquiryScanTypeCompleteView::Create(view);
|
|
ASSERT(packet.IsValid());
|
|
ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
|
|
} break;
|
|
|
|
case hci::OpCode::READ_INQUIRY_SCAN_TYPE: {
|
|
auto packet = hci::ReadInquiryScanTypeCompleteView::Create(view);
|
|
ASSERT(packet.IsValid());
|
|
ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
|
|
inquiry_scan_type_ = packet.GetInquiryScanType();
|
|
} break;
|
|
|
|
default:
|
|
LOG_WARN("Unhandled command:%s", hci::OpCodeText(view.GetCommandOpCode()).c_str());
|
|
break;
|
|
}
|
|
}
|
|
|
|
void neighbor::InquiryModule::impl::OnCommandStatus(hci::CommandStatusView status) {
|
|
ASSERT(status.GetStatus() == hci::ErrorCode::SUCCESS);
|
|
|
|
switch (status.GetCommandOpCode()) {
|
|
case hci::OpCode::INQUIRY: {
|
|
auto packet = hci::InquiryStatusView::Create(status);
|
|
ASSERT(packet.IsValid());
|
|
if (active_limited_one_shot_ || active_general_one_shot_) {
|
|
LOG_INFO("Inquiry started lap: %s", active_limited_one_shot_ ? "Limited" : "General");
|
|
}
|
|
} break;
|
|
|
|
default:
|
|
LOG_WARN("Unhandled command:%s", hci::OpCodeText(status.GetCommandOpCode()).c_str());
|
|
break;
|
|
}
|
|
}
|
|
|
|
void neighbor::InquiryModule::impl::OnEvent(hci::EventView view) {
|
|
switch (view.GetEventCode()) {
|
|
case hci::EventCode::INQUIRY_COMPLETE: {
|
|
auto packet = hci::InquiryCompleteView::Create(view);
|
|
ASSERT(packet.IsValid());
|
|
LOG_INFO("inquiry complete");
|
|
active_limited_one_shot_ = false;
|
|
active_general_one_shot_ = false;
|
|
inquiry_callbacks_.complete(packet.GetStatus());
|
|
} break;
|
|
|
|
case hci::EventCode::INQUIRY_RESULT: {
|
|
auto packet = hci::InquiryResultView::Create(view);
|
|
ASSERT(packet.IsValid());
|
|
LOG_INFO("Inquiry result size:%zd num_responses:%zu", packet.size(), packet.GetInquiryResults().size());
|
|
inquiry_callbacks_.result(packet);
|
|
} break;
|
|
|
|
case hci::EventCode::INQUIRY_RESULT_WITH_RSSI: {
|
|
auto packet = hci::InquiryResultWithRssiView::Create(view);
|
|
ASSERT(packet.IsValid());
|
|
LOG_INFO("Inquiry result with rssi num_responses:%zu", packet.GetInquiryResults().size());
|
|
inquiry_callbacks_.result_with_rssi(packet);
|
|
} break;
|
|
|
|
case hci::EventCode::EXTENDED_INQUIRY_RESULT: {
|
|
auto packet = hci::ExtendedInquiryResultView::Create(view);
|
|
ASSERT(packet.IsValid());
|
|
LOG_INFO(
|
|
"Extended inquiry result addr:%s repetition_mode:%s cod:%s clock_offset:%d rssi:%hhd",
|
|
packet.GetAddress().ToString().c_str(),
|
|
hci::PageScanRepetitionModeText(packet.GetPageScanRepetitionMode()).c_str(),
|
|
packet.GetClassOfDevice().ToString().c_str(),
|
|
packet.GetClockOffset(),
|
|
packet.GetRssi());
|
|
inquiry_callbacks_.extended_result(packet);
|
|
} break;
|
|
|
|
default:
|
|
LOG_ERROR("Unhandled event:%s", hci::EventCodeText(view.GetEventCode()).c_str());
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* impl
|
|
*/
|
|
void neighbor::InquiryModule::impl::RegisterCallbacks(InquiryCallbacks callbacks) {
|
|
inquiry_callbacks_ = callbacks;
|
|
|
|
hci_layer_->RegisterEventHandler(
|
|
hci::EventCode::INQUIRY_RESULT, handler_->BindOn(this, &InquiryModule::impl::OnEvent));
|
|
hci_layer_->RegisterEventHandler(
|
|
hci::EventCode::INQUIRY_RESULT_WITH_RSSI, handler_->BindOn(this, &InquiryModule::impl::OnEvent));
|
|
hci_layer_->RegisterEventHandler(
|
|
hci::EventCode::EXTENDED_INQUIRY_RESULT, handler_->BindOn(this, &InquiryModule::impl::OnEvent));
|
|
hci_layer_->RegisterEventHandler(
|
|
hci::EventCode::INQUIRY_COMPLETE, handler_->BindOn(this, &InquiryModule::impl::OnEvent));
|
|
}
|
|
|
|
void neighbor::InquiryModule::impl::UnregisterCallbacks() {
|
|
hci_layer_->UnregisterEventHandler(hci::EventCode::INQUIRY_COMPLETE);
|
|
hci_layer_->UnregisterEventHandler(hci::EventCode::EXTENDED_INQUIRY_RESULT);
|
|
hci_layer_->UnregisterEventHandler(hci::EventCode::INQUIRY_RESULT_WITH_RSSI);
|
|
hci_layer_->UnregisterEventHandler(hci::EventCode::INQUIRY_RESULT);
|
|
|
|
inquiry_callbacks_ = {nullptr, nullptr, nullptr, nullptr};
|
|
}
|
|
|
|
void neighbor::InquiryModule::impl::EnqueueCommandComplete(std::unique_ptr<hci::CommandBuilder> command) {
|
|
hci_layer_->EnqueueCommand(std::move(command), handler_->BindOnceOn(this, &impl::OnCommandComplete));
|
|
}
|
|
|
|
void neighbor::InquiryModule::impl::EnqueueCommandStatus(std::unique_ptr<hci::CommandBuilder> command) {
|
|
hci_layer_->EnqueueCommand(std::move(command), handler_->BindOnceOn(this, &impl::OnCommandStatus));
|
|
}
|
|
|
|
void neighbor::InquiryModule::impl::EnqueueCommandCompleteSync(std::unique_ptr<hci::CommandBuilder> command) {
|
|
ASSERT(command_sync_ == nullptr);
|
|
command_sync_ = new std::promise<void>();
|
|
auto command_received = command_sync_->get_future();
|
|
hci_layer_->EnqueueCommand(std::move(command), handler_->BindOnceOn(this, &impl::OnCommandCompleteSync));
|
|
command_received.wait();
|
|
delete command_sync_;
|
|
command_sync_ = nullptr;
|
|
}
|
|
|
|
void neighbor::InquiryModule::impl::StartOneShotInquiry(
|
|
bool limited, InquiryLength inquiry_length, NumResponses num_responses) {
|
|
ASSERT(HasCallbacks());
|
|
ASSERT(!IsInquiryActive());
|
|
hci::Lap lap;
|
|
if (limited) {
|
|
active_limited_one_shot_ = true;
|
|
lap.lap_ = kLimitedInquiryAccessCode;
|
|
} else {
|
|
active_general_one_shot_ = true;
|
|
lap.lap_ = kGeneralInquiryAccessCode;
|
|
}
|
|
EnqueueCommandStatus(hci::InquiryBuilder::Create(lap, inquiry_length, num_responses));
|
|
}
|
|
|
|
void neighbor::InquiryModule::impl::StopOneShotInquiry() {
|
|
ASSERT(active_general_one_shot_ || active_limited_one_shot_);
|
|
active_general_one_shot_ = false;
|
|
active_limited_one_shot_ = false;
|
|
EnqueueCommandComplete(hci::InquiryCancelBuilder::Create());
|
|
}
|
|
|
|
void neighbor::InquiryModule::impl::StartPeriodicInquiry(
|
|
bool limited,
|
|
InquiryLength inquiry_length,
|
|
NumResponses num_responses,
|
|
PeriodLength max_delay,
|
|
PeriodLength min_delay) {
|
|
ASSERT(HasCallbacks());
|
|
ASSERT(!IsInquiryActive());
|
|
hci::Lap lap;
|
|
if (limited) {
|
|
active_limited_periodic_ = true;
|
|
lap.lap_ = kLimitedInquiryAccessCode;
|
|
} else {
|
|
active_general_periodic_ = true;
|
|
lap.lap_ = kGeneralInquiryAccessCode;
|
|
}
|
|
EnqueueCommandComplete(
|
|
hci::PeriodicInquiryModeBuilder::Create(max_delay, min_delay, lap, inquiry_length, num_responses));
|
|
}
|
|
|
|
void neighbor::InquiryModule::impl::StopPeriodicInquiry() {
|
|
ASSERT(active_general_periodic_ || active_limited_periodic_);
|
|
active_general_periodic_ = false;
|
|
active_limited_periodic_ = false;
|
|
EnqueueCommandComplete(hci::ExitPeriodicInquiryModeBuilder::Create());
|
|
}
|
|
|
|
bool neighbor::InquiryModule::impl::IsInquiryActive() const {
|
|
return active_general_one_shot_ || active_limited_one_shot_ || active_limited_periodic_ || active_general_periodic_;
|
|
}
|
|
|
|
void neighbor::InquiryModule::impl::Start() {
|
|
hci_layer_ = module_.GetDependency<hci::HciLayer>();
|
|
handler_ = module_.GetHandler();
|
|
|
|
EnqueueCommandComplete(hci::ReadInquiryResponseTransmitPowerLevelBuilder::Create());
|
|
EnqueueCommandComplete(hci::ReadInquiryScanActivityBuilder::Create());
|
|
EnqueueCommandComplete(hci::ReadInquiryScanTypeBuilder::Create());
|
|
EnqueueCommandCompleteSync(hci::ReadInquiryModeBuilder::Create());
|
|
|
|
LOG_INFO("Started inquiry module");
|
|
}
|
|
|
|
void neighbor::InquiryModule::impl::Stop() {
|
|
LOG_INFO("Inquiry scan interval:%hu window:%hu", inquiry_scan_.interval, inquiry_scan_.window);
|
|
LOG_INFO(
|
|
"Inquiry mode:%s scan_type:%s",
|
|
hci::InquiryModeText(inquiry_mode_).c_str(),
|
|
hci::InquiryScanTypeText(inquiry_scan_type_).c_str());
|
|
LOG_INFO("Inquiry response tx power:%hhd", inquiry_response_tx_power_);
|
|
LOG_INFO("Stopped inquiry module");
|
|
}
|
|
|
|
void neighbor::InquiryModule::impl::SetInquiryMode(hci::InquiryMode mode) {
|
|
EnqueueCommandComplete(hci::WriteInquiryModeBuilder::Create(mode));
|
|
inquiry_mode_ = mode;
|
|
LOG_INFO("Set inquiry mode:%s", hci::InquiryModeText(mode).c_str());
|
|
}
|
|
|
|
void neighbor::InquiryModule::impl::SetScanActivity(ScanParameters params) {
|
|
EnqueueCommandComplete(hci::WriteInquiryScanActivityBuilder::Create(params.interval, params.window));
|
|
inquiry_scan_ = params;
|
|
LOG_INFO(
|
|
"Set scan activity interval:0x%x/%.02fms window:0x%x/%.02fms",
|
|
params.interval,
|
|
ScanIntervalTimeMs(params.interval),
|
|
params.window,
|
|
ScanWindowTimeMs(params.window));
|
|
}
|
|
|
|
void neighbor::InquiryModule::impl::SetScanType(hci::InquiryScanType scan_type) {
|
|
EnqueueCommandComplete(hci::WriteInquiryScanTypeBuilder::Create(scan_type));
|
|
LOG_INFO("Set scan type:%s", hci::InquiryScanTypeText(scan_type).c_str());
|
|
}
|
|
|
|
bool neighbor::InquiryModule::impl::HasCallbacks() const {
|
|
return inquiry_callbacks_.result != nullptr && inquiry_callbacks_.result_with_rssi != nullptr &&
|
|
inquiry_callbacks_.extended_result != nullptr && inquiry_callbacks_.complete != nullptr;
|
|
}
|
|
|
|
/**
|
|
* General API here
|
|
*/
|
|
neighbor::InquiryModule::InquiryModule() : pimpl_(std::make_unique<impl>(*this)) {}
|
|
|
|
neighbor::InquiryModule::~InquiryModule() {
|
|
pimpl_.reset();
|
|
}
|
|
|
|
void neighbor::InquiryModule::RegisterCallbacks(InquiryCallbacks callbacks) {
|
|
pimpl_->RegisterCallbacks(callbacks);
|
|
}
|
|
|
|
void neighbor::InquiryModule::UnregisterCallbacks() {
|
|
pimpl_->UnregisterCallbacks();
|
|
}
|
|
|
|
void neighbor::InquiryModule::StartGeneralInquiry(InquiryLength inquiry_length, NumResponses num_responses) {
|
|
GetHandler()->Post(common::BindOnce(
|
|
&neighbor::InquiryModule::impl::StartOneShotInquiry,
|
|
common::Unretained(pimpl_.get()),
|
|
false,
|
|
inquiry_length,
|
|
num_responses));
|
|
}
|
|
|
|
void neighbor::InquiryModule::StartLimitedInquiry(InquiryLength inquiry_length, NumResponses num_responses) {
|
|
GetHandler()->Post(common::BindOnce(
|
|
&neighbor::InquiryModule::impl::StartOneShotInquiry,
|
|
common::Unretained(pimpl_.get()),
|
|
true,
|
|
inquiry_length,
|
|
num_responses));
|
|
}
|
|
|
|
void neighbor::InquiryModule::StopInquiry() {
|
|
GetHandler()->Post(
|
|
common::BindOnce(&neighbor::InquiryModule::impl::StopOneShotInquiry, common::Unretained(pimpl_.get())));
|
|
}
|
|
|
|
void neighbor::InquiryModule::StartGeneralPeriodicInquiry(
|
|
InquiryLength inquiry_length, NumResponses num_responses, PeriodLength max_delay, PeriodLength min_delay) {
|
|
GetHandler()->Post(common::BindOnce(
|
|
&neighbor::InquiryModule::impl::StartPeriodicInquiry,
|
|
common::Unretained(pimpl_.get()),
|
|
false,
|
|
inquiry_length,
|
|
num_responses,
|
|
max_delay,
|
|
min_delay));
|
|
}
|
|
|
|
void neighbor::InquiryModule::StartLimitedPeriodicInquiry(
|
|
InquiryLength inquiry_length, NumResponses num_responses, PeriodLength max_delay, PeriodLength min_delay) {
|
|
GetHandler()->Post(common::BindOnce(
|
|
&neighbor::InquiryModule::impl::StartPeriodicInquiry,
|
|
common::Unretained(pimpl_.get()),
|
|
true,
|
|
inquiry_length,
|
|
num_responses,
|
|
max_delay,
|
|
min_delay));
|
|
}
|
|
|
|
void neighbor::InquiryModule::StopPeriodicInquiry() {
|
|
GetHandler()->Post(
|
|
common::BindOnce(&neighbor::InquiryModule::impl::StopPeriodicInquiry, common::Unretained(pimpl_.get())));
|
|
}
|
|
|
|
void neighbor::InquiryModule::SetScanActivity(ScanParameters params) {
|
|
GetHandler()->Post(
|
|
common::BindOnce(&neighbor::InquiryModule::impl::SetScanActivity, common::Unretained(pimpl_.get()), params));
|
|
}
|
|
|
|
void neighbor::InquiryModule::SetInterlacedScan() {
|
|
GetHandler()->Post(common::BindOnce(
|
|
&neighbor::InquiryModule::impl::SetScanType, common::Unretained(pimpl_.get()), hci::InquiryScanType::INTERLACED));
|
|
}
|
|
|
|
void neighbor::InquiryModule::SetStandardScan() {
|
|
GetHandler()->Post(common::BindOnce(
|
|
&neighbor::InquiryModule::impl::SetScanType, common::Unretained(pimpl_.get()), hci::InquiryScanType::STANDARD));
|
|
}
|
|
|
|
void neighbor::InquiryModule::SetStandardInquiryResultMode() {
|
|
GetHandler()->Post(common::BindOnce(
|
|
&neighbor::InquiryModule::impl::SetInquiryMode, common::Unretained(pimpl_.get()), hci::InquiryMode::STANDARD));
|
|
}
|
|
|
|
void neighbor::InquiryModule::SetInquiryWithRssiResultMode() {
|
|
GetHandler()->Post(common::BindOnce(
|
|
&neighbor::InquiryModule::impl::SetInquiryMode, common::Unretained(pimpl_.get()), hci::InquiryMode::RSSI));
|
|
}
|
|
|
|
void neighbor::InquiryModule::SetExtendedInquiryResultMode() {
|
|
GetHandler()->Post(common::BindOnce(
|
|
&neighbor::InquiryModule::impl::SetInquiryMode,
|
|
common::Unretained(pimpl_.get()),
|
|
hci::InquiryMode::RSSI_OR_EXTENDED));
|
|
}
|
|
|
|
/**
|
|
* Module methods here
|
|
*/
|
|
void neighbor::InquiryModule::ListDependencies(ModuleList* list) {
|
|
list->add<hci::HciLayer>();
|
|
}
|
|
|
|
void neighbor::InquiryModule::Start() {
|
|
pimpl_->Start();
|
|
}
|
|
|
|
void neighbor::InquiryModule::Stop() {
|
|
pimpl_->Stop();
|
|
}
|
|
|
|
} // namespace neighbor
|
|
} // namespace bluetooth
|