• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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