--- /dev/null
+/*
+ * 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 veiwstatus.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), common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)),
+ handler_);
+ }
+
+ {
+ std::unique_ptr<hci::ReadScanEnableBuilder> packet = hci::ReadScanEnableBuilder::Create();
+ hci_layer_->EnqueueCommand(std::move(packet), common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)),
+ handler_);
+ }
+}
+
+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), common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)),
+ handler_);
+}
+
+void neighbor::ScanModule::impl::Stop() {
+ LOG_DEBUG("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) {
+ list->add<hci::HciLayer>();
+}
+
+void neighbor::ScanModule::Start() {
+ pimpl_->Start();
+}
+
+void neighbor::ScanModule::Stop() {
+ pimpl_->Stop();
+}
+
+} // namespace neighbor
+} // namespace bluetooth
--- /dev/null
+/*
+ * 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.
+ */
+#pragma once
+
+#include <memory>
+
+#include "module.h"
+
+namespace bluetooth {
+namespace neighbor {
+
+class ScanModule : public bluetooth::Module {
+ public:
+ ScanModule();
+ ~ScanModule();
+
+ void SetInquiryScan();
+ void ClearInquiryScan();
+ bool IsInquiryEnabled() const;
+
+ void SetPageScan();
+ void ClearPageScan();
+ bool IsPageEnabled() const;
+
+ static const ModuleFactory Factory;
+
+ protected:
+ void ListDependencies(ModuleList* list) override;
+ void Start() override;
+ void Stop() override;
+
+ private:
+ struct impl;
+ std::unique_ptr<impl> pimpl_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScanModule);
+};
+
+} // namespace neighbor
+} // namespace bluetooth