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