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