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 <memory>
21
22 #include "hci/hci_layer.h"
23 #include "hci/hci_packets.h"
24 #include "module.h"
25 #include "os/handler.h"
26 #include "os/log.h"
27
28 namespace bluetooth {
29 namespace neighbor {
30
31 struct ScanModule::impl {
32 impl(ScanModule& module);
33
34 void SetInquiryScan(bool enabled);
35 bool IsInquiryEnabled() const;
36
37 void SetPageScan(bool enabled);
38 bool IsPageEnabled() const;
39
40 void Start();
41 void Stop();
42
43 private:
44 ScanModule& module_;
45
46 bool inquiry_scan_enabled_;
47 bool page_scan_enabled_;
48
49 void WriteScanEnable();
50 void ReadScanEnable(hci::ScanEnable);
51
52 void OnCommandComplete(hci::CommandCompleteView status);
53
54 hci::HciLayer* hci_layer_;
55 os::Handler* handler_;
56 };
57
__anonc1a7790f0102() 58 const ModuleFactory neighbor::ScanModule::Factory = ModuleFactory([]() { return new neighbor::ScanModule(); });
59
impl(neighbor::ScanModule & module)60 neighbor::ScanModule::impl::impl(neighbor::ScanModule& module)
61 : module_(module), inquiry_scan_enabled_(false), page_scan_enabled_(false) {}
62
OnCommandComplete(hci::CommandCompleteView view)63 void neighbor::ScanModule::impl::OnCommandComplete(hci::CommandCompleteView view) {
64 switch (view.GetCommandOpCode()) {
65 case hci::OpCode::READ_SCAN_ENABLE: {
66 auto packet = hci::ReadScanEnableCompleteView::Create(view);
67 ASSERT(packet.IsValid());
68 ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
69 ReadScanEnable(packet.GetScanEnable());
70 } break;
71
72 case hci::OpCode::WRITE_SCAN_ENABLE: {
73 auto packet = hci::WriteScanEnableCompleteView::Create(view);
74 ASSERT(packet.IsValid());
75 ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
76 } break;
77
78 default:
79 LOG_ERROR("Unhandled command %s", hci::OpCodeText(view.GetCommandOpCode()).c_str());
80 break;
81 }
82 }
83
WriteScanEnable()84 void neighbor::ScanModule::impl::WriteScanEnable() {
85 hci::ScanEnable scan_enable;
86
87 if (inquiry_scan_enabled_ && !page_scan_enabled_) {
88 scan_enable = hci::ScanEnable::INQUIRY_SCAN_ONLY;
89 } else if (!inquiry_scan_enabled_ && page_scan_enabled_) {
90 scan_enable = hci::ScanEnable::PAGE_SCAN_ONLY;
91 } else if (inquiry_scan_enabled_ && page_scan_enabled_) {
92 scan_enable = hci::ScanEnable::INQUIRY_AND_PAGE_SCAN;
93 } else {
94 scan_enable = hci::ScanEnable::NO_SCANS;
95 }
96
97 {
98 std::unique_ptr<hci::WriteScanEnableBuilder> packet = hci::WriteScanEnableBuilder::Create(scan_enable);
99 hci_layer_->EnqueueCommand(std::move(packet), handler_->BindOnceOn(this, &impl::OnCommandComplete));
100 }
101
102 {
103 std::unique_ptr<hci::ReadScanEnableBuilder> packet = hci::ReadScanEnableBuilder::Create();
104 hci_layer_->EnqueueCommand(std::move(packet), handler_->BindOnceOn(this, &impl::OnCommandComplete));
105 }
106 }
107
ReadScanEnable(hci::ScanEnable scan_enable)108 void neighbor::ScanModule::impl::ReadScanEnable(hci::ScanEnable scan_enable) {
109 switch (scan_enable) {
110 case hci::ScanEnable::INQUIRY_SCAN_ONLY:
111 inquiry_scan_enabled_ = true;
112 page_scan_enabled_ = false;
113 break;
114
115 case hci::ScanEnable::PAGE_SCAN_ONLY:
116 inquiry_scan_enabled_ = false;
117 page_scan_enabled_ = true;
118 break;
119
120 case hci::ScanEnable::INQUIRY_AND_PAGE_SCAN:
121 inquiry_scan_enabled_ = true;
122 page_scan_enabled_ = true;
123 break;
124
125 default:
126 inquiry_scan_enabled_ = false;
127 page_scan_enabled_ = false;
128 break;
129 }
130 }
131
SetInquiryScan(bool enabled)132 void neighbor::ScanModule::impl::SetInquiryScan(bool enabled) {
133 inquiry_scan_enabled_ = enabled;
134 WriteScanEnable();
135 }
136
SetPageScan(bool enabled)137 void neighbor::ScanModule::impl::SetPageScan(bool enabled) {
138 page_scan_enabled_ = enabled;
139 WriteScanEnable();
140 }
141
IsInquiryEnabled() const142 bool neighbor::ScanModule::impl::IsInquiryEnabled() const {
143 return inquiry_scan_enabled_;
144 }
145
IsPageEnabled() const146 bool neighbor::ScanModule::impl::IsPageEnabled() const {
147 return page_scan_enabled_;
148 }
149
Start()150 void neighbor::ScanModule::impl::Start() {
151 hci_layer_ = module_.GetDependency<hci::HciLayer>();
152 handler_ = module_.GetHandler();
153
154 std::unique_ptr<hci::ReadScanEnableBuilder> packet = hci::ReadScanEnableBuilder::Create();
155 hci_layer_->EnqueueCommand(std::move(packet), handler_->BindOnceOn(this, &impl::OnCommandComplete));
156 }
157
Stop()158 void neighbor::ScanModule::impl::Stop() {
159 LOG_INFO("inquiry scan enabled:%d page scan enabled:%d", inquiry_scan_enabled_, page_scan_enabled_);
160 }
161
ScanModule()162 neighbor::ScanModule::ScanModule() : pimpl_(std::make_unique<impl>(*this)) {}
163
~ScanModule()164 neighbor::ScanModule::~ScanModule() {
165 pimpl_.reset();
166 }
167
SetInquiryScan()168 void neighbor::ScanModule::SetInquiryScan() {
169 pimpl_->SetInquiryScan(true);
170 }
171
ClearInquiryScan()172 void neighbor::ScanModule::ClearInquiryScan() {
173 pimpl_->SetInquiryScan(false);
174 }
175
SetPageScan()176 void neighbor::ScanModule::SetPageScan() {
177 pimpl_->SetPageScan(true);
178 }
179
ClearPageScan()180 void neighbor::ScanModule::ClearPageScan() {
181 pimpl_->SetPageScan(false);
182 }
183
IsInquiryEnabled() const184 bool neighbor::ScanModule::IsInquiryEnabled() const {
185 return pimpl_->IsInquiryEnabled();
186 }
187
IsPageEnabled() const188 bool neighbor::ScanModule::IsPageEnabled() const {
189 return pimpl_->IsPageEnabled();
190 }
191
ListDependencies(ModuleList * list)192 void neighbor::ScanModule::ListDependencies(ModuleList* list) {
193 list->add<hci::HciLayer>();
194 }
195
Start()196 void neighbor::ScanModule::Start() {
197 pimpl_->Start();
198 }
199
Stop()200 void neighbor::ScanModule::Stop() {
201 pimpl_->Stop();
202 }
203
204 } // namespace neighbor
205 } // namespace bluetooth
206