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 =
__anon784c79370102() 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_INFO("Started discoverability module");
125 }
126
Dump() const127 void neighbor::DiscoverabilityModule::impl::Dump() const {
128 LOG_INFO("Number of supported iacs:%hhd", num_supported_iac_);
129 LOG_INFO("Number of current iacs:%zd", laps_.size());
130 for (auto it : laps_) {
131 LOG_INFO(" 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