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/discoverability.h"
19 
20 #include <memory>
21 
22 #include "common/bind.h"
23 #include "hci/hci_layer.h"
24 #include "hci/hci_packets.h"
25 #include "module.h"
26 #include "neighbor/scan.h"
27 #include "os/handler.h"
28 #include "os/log.h"
29 
30 namespace bluetooth {
31 namespace neighbor {
32 
33 static constexpr uint8_t kGeneralInquiryAccessCode = 0x33;
34 static constexpr uint8_t kLimitedInquiryAccessCode = 0x00;
35 
36 struct DiscoverabilityModule::impl {
37   void StartDiscoverability(std::vector<hci::Lap>& laps);
38   void StopDiscoverability();
39 
40   bool IsGeneralDiscoverabilityEnabled() const;
41   bool IsLimitedDiscoverabilityEnabled() const;
42 
43   void Start();
44 
45   impl(DiscoverabilityModule& discoverability_module);
46 
47  private:
48   uint8_t num_supported_iac_;
49   std::vector<hci::Lap> laps_;
50 
51   void OnCommandComplete(hci::CommandCompleteView status);
52 
53   hci::HciLayer* hci_layer_;
54   neighbor::ScanModule* scan_module_;
55   os::Handler* handler_;
56 
57   DiscoverabilityModule& module_;
58   void Dump() const;
59 };
60 
61 const ModuleFactory neighbor::DiscoverabilityModule::Factory =
__anon290c71500102() 62     ModuleFactory([]() { return new neighbor::DiscoverabilityModule(); });
63 
impl(neighbor::DiscoverabilityModule & module)64 neighbor::DiscoverabilityModule::impl::impl(neighbor::DiscoverabilityModule& module) : module_(module) {}
65 
OnCommandComplete(hci::CommandCompleteView status)66 void neighbor::DiscoverabilityModule::impl::OnCommandComplete(hci::CommandCompleteView status) {
67   switch (status.GetCommandOpCode()) {
68     case hci::OpCode::READ_CURRENT_IAC_LAP: {
69       auto packet = hci::ReadCurrentIacLapCompleteView::Create(status);
70       ASSERT(packet.IsValid());
71       ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
72       laps_ = packet.GetLapsToRead();
73     } break;
74 
75     case hci::OpCode::WRITE_CURRENT_IAC_LAP: {
76       auto packet = hci::WriteCurrentIacLapCompleteView::Create(status);
77       ASSERT(packet.IsValid());
78       ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
79     } break;
80 
81     case hci::OpCode::READ_NUMBER_OF_SUPPORTED_IAC: {
82       auto packet = hci::ReadNumberOfSupportedIacCompleteView::Create(status);
83       ASSERT(packet.IsValid());
84       ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
85       num_supported_iac_ = packet.GetNumSupportIac();
86     } break;
87     default:
88       LOG_WARN("Unhandled command:%s", hci::OpCodeText(status.GetCommandOpCode()).c_str());
89       break;
90   }
91 }
92 
StartDiscoverability(std::vector<hci::Lap> & laps)93 void neighbor::DiscoverabilityModule::impl::StartDiscoverability(std::vector<hci::Lap>& laps) {
94   ASSERT(laps.size() <= num_supported_iac_);
95   hci_layer_->EnqueueCommand(
96       hci::WriteCurrentIacLapBuilder::Create(laps), handler_->BindOnceOn(this, &impl::OnCommandComplete));
97   hci_layer_->EnqueueCommand(
98       hci::ReadCurrentIacLapBuilder::Create(), handler_->BindOnceOn(this, &impl::OnCommandComplete));
99   scan_module_->SetInquiryScan();
100 }
101 
StopDiscoverability()102 void neighbor::DiscoverabilityModule::impl::StopDiscoverability() {
103   scan_module_->ClearInquiryScan();
104 }
105 
IsGeneralDiscoverabilityEnabled() const106 bool neighbor::DiscoverabilityModule::impl::IsGeneralDiscoverabilityEnabled() const {
107   return scan_module_->IsInquiryEnabled() && laps_.size() == 1;
108 }
109 
IsLimitedDiscoverabilityEnabled() const110 bool neighbor::DiscoverabilityModule::impl::IsLimitedDiscoverabilityEnabled() const {
111   return scan_module_->IsInquiryEnabled() && laps_.size() == 2;
112 }
113 
Start()114 void neighbor::DiscoverabilityModule::impl::Start() {
115   hci_layer_ = module_.GetDependency<hci::HciLayer>();
116   scan_module_ = module_.GetDependency<neighbor::ScanModule>();
117   handler_ = module_.GetHandler();
118 
119   hci_layer_->EnqueueCommand(
120       hci::ReadCurrentIacLapBuilder::Create(), handler_->BindOnceOn(this, &impl::OnCommandComplete));
121 
122   hci_layer_->EnqueueCommand(
123       hci::ReadNumberOfSupportedIacBuilder::Create(), handler_->BindOnceOn(this, &impl::OnCommandComplete));
124   LOG_DEBUG("Started discoverability module");
125 }
126 
Dump() const127 void neighbor::DiscoverabilityModule::impl::Dump() const {
128   LOG_DEBUG("Number of supported iacs:%hhd", num_supported_iac_);
129   LOG_DEBUG("Number of current iacs:%zd", laps_.size());
130   for (auto it : laps_) {
131     LOG_DEBUG("  discoverability lap:%x", it.lap_);
132   }
133 }
134 
DiscoverabilityModule()135 neighbor::DiscoverabilityModule::DiscoverabilityModule() : pimpl_(std::make_unique<impl>(*this)) {}
136 
~DiscoverabilityModule()137 neighbor::DiscoverabilityModule::~DiscoverabilityModule() {
138   pimpl_.reset();
139 }
140 
StartGeneralDiscoverability()141 void neighbor::DiscoverabilityModule::StartGeneralDiscoverability() {
142   std::vector<hci::Lap> laps;
143   {
144     hci::Lap lap;
145     lap.lap_ = kGeneralInquiryAccessCode;
146     laps.push_back(lap);
147   }
148   pimpl_->StartDiscoverability(laps);
149 }
150 
StartLimitedDiscoverability()151 void neighbor::DiscoverabilityModule::StartLimitedDiscoverability() {
152   std::vector<hci::Lap> laps;
153   {
154     hci::Lap lap;
155     lap.lap_ = kGeneralInquiryAccessCode;
156     laps.push_back(lap);
157   }
158 
159   {
160     hci::Lap lap;
161     lap.lap_ = kLimitedInquiryAccessCode;
162     laps.push_back(lap);
163   }
164   pimpl_->StartDiscoverability(laps);
165 }
166 
StopDiscoverability()167 void neighbor::DiscoverabilityModule::StopDiscoverability() {
168   pimpl_->StopDiscoverability();
169 }
170 
IsGeneralDiscoverabilityEnabled() const171 bool neighbor::DiscoverabilityModule::IsGeneralDiscoverabilityEnabled() const {
172   return pimpl_->IsGeneralDiscoverabilityEnabled();
173 }
174 
IsLimitedDiscoverabilityEnabled() const175 bool neighbor::DiscoverabilityModule::IsLimitedDiscoverabilityEnabled() const {
176   return pimpl_->IsLimitedDiscoverabilityEnabled();
177 }
178 
179 /**
180  * Module stuff
181  */
ListDependencies(ModuleList * list)182 void neighbor::DiscoverabilityModule::ListDependencies(ModuleList* list) {
183   list->add<hci::HciLayer>();
184   list->add<neighbor::ScanModule>();
185 }
186 
Start()187 void neighbor::DiscoverabilityModule::Start() {
188   pimpl_->Start();
189 }
190 
Stop()191 void neighbor::DiscoverabilityModule::Stop() {}
192 
193 }  // namespace neighbor
194 }  // namespace bluetooth
195