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 #include "os/log.h"
29
30 namespace bluetooth {
31 namespace neighbor {
32
33 struct ScanModule::impl {
34 impl(ScanModule& module);
35
36 void SetInquiryScan(bool enabled);
37 bool IsInquiryEnabled() const;
38
39 void SetPageScan(bool enabled);
40 bool IsPageEnabled() const;
41
42 void Start();
43 void Stop();
44
45 private:
46 ScanModule& module_;
47
48 bool inquiry_scan_enabled_;
49 bool page_scan_enabled_;
50
51 void WriteScanEnable();
52 void ReadScanEnable(hci::ScanEnable);
53
54 void OnCommandComplete(hci::CommandCompleteView status);
55
56 hci::HciLayer* hci_layer_;
57 os::Handler* handler_;
58 };
59
__anond829b49e0102() 60 const ModuleFactory neighbor::ScanModule::Factory = 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(
71 packet.GetStatus() == hci::ErrorCode::SUCCESS,
72 "assert failed: packet.GetStatus() == hci::ErrorCode::SUCCESS");
73 ReadScanEnable(packet.GetScanEnable());
74 } break;
75
76 case hci::OpCode::WRITE_SCAN_ENABLE: {
77 auto packet = hci::WriteScanEnableCompleteView::Create(view);
78 log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()");
79 log::assert_that(
80 packet.GetStatus() == hci::ErrorCode::SUCCESS,
81 "assert failed: packet.GetStatus() == hci::ErrorCode::SUCCESS");
82 } break;
83
84 default:
85 log::error("Unhandled command {}", hci::OpCodeText(view.GetCommandOpCode()));
86 break;
87 }
88 }
89
WriteScanEnable()90 void neighbor::ScanModule::impl::WriteScanEnable() {
91 hci::ScanEnable scan_enable;
92
93 if (inquiry_scan_enabled_ && !page_scan_enabled_) {
94 scan_enable = hci::ScanEnable::INQUIRY_SCAN_ONLY;
95 } else if (!inquiry_scan_enabled_ && page_scan_enabled_) {
96 scan_enable = hci::ScanEnable::PAGE_SCAN_ONLY;
97 } else if (inquiry_scan_enabled_ && page_scan_enabled_) {
98 scan_enable = hci::ScanEnable::INQUIRY_AND_PAGE_SCAN;
99 } else {
100 scan_enable = hci::ScanEnable::NO_SCANS;
101 }
102
103 {
104 std::unique_ptr<hci::WriteScanEnableBuilder> packet = hci::WriteScanEnableBuilder::Create(scan_enable);
105 hci_layer_->EnqueueCommand(std::move(packet), 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), handler_->BindOnceOn(this, &impl::OnCommandComplete));
111 }
112 }
113
ReadScanEnable(hci::ScanEnable scan_enable)114 void neighbor::ScanModule::impl::ReadScanEnable(hci::ScanEnable scan_enable) {
115 switch (scan_enable) {
116 case hci::ScanEnable::INQUIRY_SCAN_ONLY:
117 inquiry_scan_enabled_ = true;
118 page_scan_enabled_ = false;
119 break;
120
121 case hci::ScanEnable::PAGE_SCAN_ONLY:
122 inquiry_scan_enabled_ = false;
123 page_scan_enabled_ = true;
124 break;
125
126 case hci::ScanEnable::INQUIRY_AND_PAGE_SCAN:
127 inquiry_scan_enabled_ = true;
128 page_scan_enabled_ = true;
129 break;
130
131 default:
132 inquiry_scan_enabled_ = false;
133 page_scan_enabled_ = false;
134 break;
135 }
136 }
137
SetInquiryScan(bool enabled)138 void neighbor::ScanModule::impl::SetInquiryScan(bool enabled) {
139 inquiry_scan_enabled_ = enabled;
140 WriteScanEnable();
141 }
142
SetPageScan(bool enabled)143 void neighbor::ScanModule::impl::SetPageScan(bool enabled) {
144 page_scan_enabled_ = enabled;
145 WriteScanEnable();
146 }
147
IsInquiryEnabled() const148 bool neighbor::ScanModule::impl::IsInquiryEnabled() const {
149 return inquiry_scan_enabled_;
150 }
151
IsPageEnabled() const152 bool neighbor::ScanModule::impl::IsPageEnabled() const {
153 return page_scan_enabled_;
154 }
155
Start()156 void neighbor::ScanModule::impl::Start() {
157 hci_layer_ = module_.GetDependency<hci::HciLayer>();
158 handler_ = module_.GetHandler();
159
160 std::unique_ptr<hci::ReadScanEnableBuilder> packet = hci::ReadScanEnableBuilder::Create();
161 hci_layer_->EnqueueCommand(std::move(packet), handler_->BindOnceOn(this, &impl::OnCommandComplete));
162 }
163
Stop()164 void neighbor::ScanModule::impl::Stop() {
165 log::info(
166 "inquiry scan enabled:{} page scan enabled:{}", inquiry_scan_enabled_, page_scan_enabled_);
167 }
168
ScanModule()169 neighbor::ScanModule::ScanModule() : pimpl_(std::make_unique<impl>(*this)) {}
170
~ScanModule()171 neighbor::ScanModule::~ScanModule() {
172 pimpl_.reset();
173 }
174
SetInquiryScan()175 void neighbor::ScanModule::SetInquiryScan() {
176 pimpl_->SetInquiryScan(true);
177 }
178
ClearInquiryScan()179 void neighbor::ScanModule::ClearInquiryScan() {
180 pimpl_->SetInquiryScan(false);
181 }
182
SetPageScan()183 void neighbor::ScanModule::SetPageScan() {
184 pimpl_->SetPageScan(true);
185 }
186
ClearPageScan()187 void neighbor::ScanModule::ClearPageScan() {
188 pimpl_->SetPageScan(false);
189 }
190
IsInquiryEnabled() const191 bool neighbor::ScanModule::IsInquiryEnabled() const {
192 return pimpl_->IsInquiryEnabled();
193 }
194
IsPageEnabled() const195 bool neighbor::ScanModule::IsPageEnabled() const {
196 return pimpl_->IsPageEnabled();
197 }
198
ListDependencies(ModuleList * list) const199 void neighbor::ScanModule::ListDependencies(ModuleList* list) const {
200 list->add<hci::HciLayer>();
201 }
202
Start()203 void neighbor::ScanModule::Start() {
204 pimpl_->Start();
205 }
206
Stop()207 void neighbor::ScanModule::Stop() {
208 pimpl_->Stop();
209 }
210
211 } // namespace neighbor
212 } // namespace bluetooth
213