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 #include <memory>
20 #include "hci/hci_layer.h"
21 #include "hci/hci_packets.h"
22 #include "module.h"
23 #include "os/handler.h"
24 #include "os/log.h"
25
26 namespace bluetooth {
27 namespace neighbor {
28
29 struct ScanModule::impl {
30 impl(ScanModule& module);
31
32 void SetInquiryScan(bool enabled);
33 bool IsInquiryEnabled() const;
34
35 void SetPageScan(bool enabled);
36 bool IsPageEnabled() const;
37
38 void Start();
39 void Stop();
40
41 private:
42 ScanModule& module_;
43
44 bool inquiry_scan_enabled_;
45 bool page_scan_enabled_;
46
47 void WriteScanEnable();
48 void ReadScanEnable(hci::ScanEnable);
49
50 void OnCommandComplete(hci::CommandCompleteView status);
51
52 hci::HciLayer* hci_layer_;
53 os::Handler* handler_;
54 };
55
__anon98247f330102() 56 const ModuleFactory neighbor::ScanModule::Factory = ModuleFactory([]() { return new neighbor::ScanModule(); });
57
impl(neighbor::ScanModule & module)58 neighbor::ScanModule::impl::impl(neighbor::ScanModule& module)
59 : module_(module), inquiry_scan_enabled_(false), page_scan_enabled_(false) {}
60
OnCommandComplete(hci::CommandCompleteView view)61 void neighbor::ScanModule::impl::OnCommandComplete(hci::CommandCompleteView view) {
62 switch (view.GetCommandOpCode()) {
63 case hci::OpCode::READ_SCAN_ENABLE: {
64 auto packet = hci::ReadScanEnableCompleteView::Create(view);
65 ASSERT(packet.IsValid());
66 ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
67 ReadScanEnable(packet.GetScanEnable());
68 } break;
69
70 case hci::OpCode::WRITE_SCAN_ENABLE: {
71 auto packet = hci::WriteScanEnableCompleteView::Create(view);
72 ASSERT(packet.IsValid());
73 ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
74 } break;
75
76 default:
77 LOG_ERROR("Unhandled command %s", hci::OpCodeText(view.GetCommandOpCode()).c_str());
78 break;
79 }
80 }
81
WriteScanEnable()82 void neighbor::ScanModule::impl::WriteScanEnable() {
83 hci::ScanEnable scan_enable;
84
85 if (inquiry_scan_enabled_ && !page_scan_enabled_) {
86 scan_enable = hci::ScanEnable::INQUIRY_SCAN_ONLY;
87 } else if (!inquiry_scan_enabled_ && page_scan_enabled_) {
88 scan_enable = hci::ScanEnable::PAGE_SCAN_ONLY;
89 } else if (inquiry_scan_enabled_ && page_scan_enabled_) {
90 scan_enable = hci::ScanEnable::INQUIRY_AND_PAGE_SCAN;
91 } else {
92 scan_enable = hci::ScanEnable::NO_SCANS;
93 }
94
95 {
96 std::unique_ptr<hci::WriteScanEnableBuilder> packet = hci::WriteScanEnableBuilder::Create(scan_enable);
97 hci_layer_->EnqueueCommand(std::move(packet), common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)),
98 handler_);
99 }
100
101 {
102 std::unique_ptr<hci::ReadScanEnableBuilder> packet = hci::ReadScanEnableBuilder::Create();
103 hci_layer_->EnqueueCommand(std::move(packet), common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)),
104 handler_);
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), common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)),
156 handler_);
157 }
158
Stop()159 void neighbor::ScanModule::impl::Stop() {
160 LOG_DEBUG("inquiry scan enabled:%d page scan enabled:%d", inquiry_scan_enabled_, page_scan_enabled_);
161 }
162
ScanModule()163 neighbor::ScanModule::ScanModule() : pimpl_(std::make_unique<impl>(*this)) {}
164
~ScanModule()165 neighbor::ScanModule::~ScanModule() {
166 pimpl_.reset();
167 }
168
SetInquiryScan()169 void neighbor::ScanModule::SetInquiryScan() {
170 pimpl_->SetInquiryScan(true);
171 }
172
ClearInquiryScan()173 void neighbor::ScanModule::ClearInquiryScan() {
174 pimpl_->SetInquiryScan(false);
175 }
176
SetPageScan()177 void neighbor::ScanModule::SetPageScan() {
178 pimpl_->SetPageScan(true);
179 }
180
ClearPageScan()181 void neighbor::ScanModule::ClearPageScan() {
182 pimpl_->SetPageScan(false);
183 }
184
IsInquiryEnabled() const185 bool neighbor::ScanModule::IsInquiryEnabled() const {
186 return pimpl_->IsInquiryEnabled();
187 }
188
IsPageEnabled() const189 bool neighbor::ScanModule::IsPageEnabled() const {
190 return pimpl_->IsPageEnabled();
191 }
192
ListDependencies(ModuleList * list)193 void neighbor::ScanModule::ListDependencies(ModuleList* list) {
194 list->add<hci::HciLayer>();
195 }
196
Start()197 void neighbor::ScanModule::Start() {
198 pimpl_->Start();
199 }
200
Stop()201 void neighbor::ScanModule::Stop() {
202 pimpl_->Stop();
203 }
204
205 } // namespace neighbor
206 } // namespace bluetooth
207