1 /*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #define LOG_TAG "bt_gd_neigh"
17
18 #include "neighbor/scan.h"
19
20 #include <bluetooth/log.h>
21
22 #include <memory>
23
24 #include "hci/hci_layer.h"
25 #include "hci/hci_packets.h"
26 #include "module.h"
27 #include "os/handler.h"
28
29 namespace bluetooth {
30 namespace neighbor {
31
32 struct ScanModule::impl {
33 impl(ScanModule& module);
34
35 void SetInquiryScan(bool enabled);
36 bool IsInquiryEnabled() const;
37
38 void SetPageScan(bool enabled);
39 bool IsPageEnabled() const;
40
41 void Start();
42 void Stop();
43
44 private:
45 ScanModule& module_;
46
47 bool inquiry_scan_enabled_;
48 bool page_scan_enabled_;
49
50 void WriteScanEnable();
51 void ReadScanEnable(hci::ScanEnable);
52
53 void OnCommandComplete(hci::CommandCompleteView status);
54
55 hci::HciLayer* hci_layer_;
56 os::Handler* handler_;
57 };
58
59 const ModuleFactory neighbor::ScanModule::Factory =
__anonda6385940102() 60 ModuleFactory([]() { return new neighbor::ScanModule(); });
61
impl(neighbor::ScanModule & module)62 neighbor::ScanModule::impl::impl(neighbor::ScanModule& module)
63 : module_(module), inquiry_scan_enabled_(false), page_scan_enabled_(false) {}
64
OnCommandComplete(hci::CommandCompleteView view)65 void neighbor::ScanModule::impl::OnCommandComplete(hci::CommandCompleteView view) {
66 switch (view.GetCommandOpCode()) {
67 case hci::OpCode::READ_SCAN_ENABLE: {
68 auto packet = hci::ReadScanEnableCompleteView::Create(view);
69 log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()");
70 log::assert_that(packet.GetStatus() == hci::ErrorCode::SUCCESS,
71 "assert failed: packet.GetStatus() == hci::ErrorCode::SUCCESS");
72 ReadScanEnable(packet.GetScanEnable());
73 } break;
74
75 case hci::OpCode::WRITE_SCAN_ENABLE: {
76 auto packet = hci::WriteScanEnableCompleteView::Create(view);
77 log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()");
78 log::assert_that(packet.GetStatus() == hci::ErrorCode::SUCCESS,
79 "assert failed: packet.GetStatus() == hci::ErrorCode::SUCCESS");
80 } break;
81
82 default:
83 log::error("Unhandled command {}", hci::OpCodeText(view.GetCommandOpCode()));
84 break;
85 }
86 }
87
WriteScanEnable()88 void neighbor::ScanModule::impl::WriteScanEnable() {
89 hci::ScanEnable scan_enable;
90
91 if (inquiry_scan_enabled_ && !page_scan_enabled_) {
92 scan_enable = hci::ScanEnable::INQUIRY_SCAN_ONLY;
93 } else if (!inquiry_scan_enabled_ && page_scan_enabled_) {
94 scan_enable = hci::ScanEnable::PAGE_SCAN_ONLY;
95 } else if (inquiry_scan_enabled_ && page_scan_enabled_) {
96 scan_enable = hci::ScanEnable::INQUIRY_AND_PAGE_SCAN;
97 } else {
98 scan_enable = hci::ScanEnable::NO_SCANS;
99 }
100
101 {
102 std::unique_ptr<hci::WriteScanEnableBuilder> packet =
103 hci::WriteScanEnableBuilder::Create(scan_enable);
104 hci_layer_->EnqueueCommand(std::move(packet),
105 handler_->BindOnceOn(this, &impl::OnCommandComplete));
106 }
107
108 {
109 std::unique_ptr<hci::ReadScanEnableBuilder> packet = hci::ReadScanEnableBuilder::Create();
110 hci_layer_->EnqueueCommand(std::move(packet),
111 handler_->BindOnceOn(this, &impl::OnCommandComplete));
112 }
113 }
114
ReadScanEnable(hci::ScanEnable scan_enable)115 void neighbor::ScanModule::impl::ReadScanEnable(hci::ScanEnable scan_enable) {
116 switch (scan_enable) {
117 case hci::ScanEnable::INQUIRY_SCAN_ONLY:
118 inquiry_scan_enabled_ = true;
119 page_scan_enabled_ = false;
120 break;
121
122 case hci::ScanEnable::PAGE_SCAN_ONLY:
123 inquiry_scan_enabled_ = false;
124 page_scan_enabled_ = true;
125 break;
126
127 case hci::ScanEnable::INQUIRY_AND_PAGE_SCAN:
128 inquiry_scan_enabled_ = true;
129 page_scan_enabled_ = true;
130 break;
131
132 default:
133 inquiry_scan_enabled_ = false;
134 page_scan_enabled_ = false;
135 break;
136 }
137 }
138
SetInquiryScan(bool enabled)139 void neighbor::ScanModule::impl::SetInquiryScan(bool enabled) {
140 inquiry_scan_enabled_ = enabled;
141 WriteScanEnable();
142 }
143
SetPageScan(bool enabled)144 void neighbor::ScanModule::impl::SetPageScan(bool enabled) {
145 page_scan_enabled_ = enabled;
146 WriteScanEnable();
147 }
148
IsInquiryEnabled() const149 bool neighbor::ScanModule::impl::IsInquiryEnabled() const { return inquiry_scan_enabled_; }
150
IsPageEnabled() const151 bool neighbor::ScanModule::impl::IsPageEnabled() const { return page_scan_enabled_; }
152
Start()153 void neighbor::ScanModule::impl::Start() {
154 hci_layer_ = module_.GetDependency<hci::HciLayer>();
155 handler_ = module_.GetHandler();
156
157 std::unique_ptr<hci::ReadScanEnableBuilder> packet = hci::ReadScanEnableBuilder::Create();
158 hci_layer_->EnqueueCommand(std::move(packet),
159 handler_->BindOnceOn(this, &impl::OnCommandComplete));
160 }
161
Stop()162 void neighbor::ScanModule::impl::Stop() {
163 log::info("inquiry scan enabled:{} page scan enabled:{}", inquiry_scan_enabled_,
164 page_scan_enabled_);
165 }
166
ScanModule()167 neighbor::ScanModule::ScanModule() : pimpl_(std::make_unique<impl>(*this)) {}
168
~ScanModule()169 neighbor::ScanModule::~ScanModule() { pimpl_.reset(); }
170
SetInquiryScan()171 void neighbor::ScanModule::SetInquiryScan() { pimpl_->SetInquiryScan(true); }
172
ClearInquiryScan()173 void neighbor::ScanModule::ClearInquiryScan() { pimpl_->SetInquiryScan(false); }
174
SetPageScan()175 void neighbor::ScanModule::SetPageScan() { pimpl_->SetPageScan(true); }
176
ClearPageScan()177 void neighbor::ScanModule::ClearPageScan() { pimpl_->SetPageScan(false); }
178
IsInquiryEnabled() const179 bool neighbor::ScanModule::IsInquiryEnabled() const { return pimpl_->IsInquiryEnabled(); }
180
IsPageEnabled() const181 bool neighbor::ScanModule::IsPageEnabled() const { return pimpl_->IsPageEnabled(); }
182
ListDependencies(ModuleList * list) const183 void neighbor::ScanModule::ListDependencies(ModuleList* list) const { list->add<hci::HciLayer>(); }
184
Start()185 void neighbor::ScanModule::Start() { pimpl_->Start(); }
186
Stop()187 void neighbor::ScanModule::Stop() { pimpl_->Stop(); }
188
189 } // namespace neighbor
190 } // namespace bluetooth
191