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 <memory>
19
20 #include "common/bind.h"
21 #include "hci/hci_layer.h"
22 #include "hci/hci_packets.h"
23 #include "module.h"
24 #include "neighbor/page.h"
25 #include "neighbor/scan_parameters.h"
26 #include "os/handler.h"
27 #include "os/log.h"
28
29 namespace bluetooth {
30 namespace neighbor {
31
32 struct PageModule::impl {
33 void SetScanActivity(ScanParameters params);
34 ScanParameters GetScanActivity() const;
35
36 void SetScanType(hci::PageScanType type);
37
38 void SetTimeout(PageTimeout timeout);
39
40 void Start();
41 void Stop();
42
43 impl(PageModule& page_module);
44
45 private:
46 PageModule& module_;
47
48 ScanParameters scan_parameters_;
49 hci::PageScanType scan_type_;
50 PageTimeout timeout_;
51
52 void OnCommandComplete(hci::CommandCompleteView status);
53
54 hci::HciLayer* hci_layer_;
55 os::Handler* handler_;
56 };
57
__anonacf31b4b0102() 58 const ModuleFactory neighbor::PageModule::Factory = ModuleFactory([]() { return new neighbor::PageModule(); });
59
impl(neighbor::PageModule & module)60 neighbor::PageModule::impl::impl(neighbor::PageModule& module) : module_(module) {}
61
OnCommandComplete(hci::CommandCompleteView view)62 void neighbor::PageModule::impl::OnCommandComplete(hci::CommandCompleteView view) {
63 switch (view.GetCommandOpCode()) {
64 case hci::OpCode::WRITE_PAGE_SCAN_ACTIVITY: {
65 auto packet = hci::WritePageScanActivityCompleteView::Create(view);
66 ASSERT(packet.IsValid());
67 ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
68 } break;
69
70 case hci::OpCode::READ_PAGE_SCAN_ACTIVITY: {
71 auto packet = hci::ReadPageScanActivityCompleteView::Create(view);
72 ASSERT(packet.IsValid());
73 ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
74 scan_parameters_.interval = packet.GetPageScanInterval();
75 scan_parameters_.window = packet.GetPageScanWindow();
76 } break;
77
78 case hci::OpCode::WRITE_PAGE_SCAN_TYPE: {
79 auto packet = hci::WritePageScanTypeCompleteView::Create(view);
80 ASSERT(packet.IsValid());
81 ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
82 } break;
83
84 case hci::OpCode::READ_PAGE_SCAN_TYPE: {
85 auto packet = hci::ReadPageScanTypeCompleteView::Create(view);
86 ASSERT(packet.IsValid());
87 ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
88 scan_type_ = packet.GetPageScanType();
89 } break;
90
91 case hci::OpCode::WRITE_PAGE_TIMEOUT: {
92 auto packet = hci::WritePageTimeoutCompleteView::Create(view);
93 ASSERT(packet.IsValid());
94 ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
95 } break;
96
97 case hci::OpCode::READ_PAGE_TIMEOUT: {
98 auto packet = hci::ReadPageTimeoutCompleteView::Create(view);
99 ASSERT(packet.IsValid());
100 ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS);
101 timeout_ = packet.GetPageTimeout();
102 } break;
103
104 default:
105 LOG_ERROR("Unhandled command %s", hci::OpCodeText(view.GetCommandOpCode()).c_str());
106 break;
107 }
108 }
109
Start()110 void neighbor::PageModule::impl::Start() {
111 hci_layer_ = module_.GetDependency<hci::HciLayer>();
112 handler_ = module_.GetHandler();
113
114 hci_layer_->EnqueueCommand(hci::ReadPageScanActivityBuilder::Create(),
115 common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), handler_);
116
117 hci_layer_->EnqueueCommand(hci::ReadPageScanTypeBuilder::Create(),
118 common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), handler_);
119
120 hci_layer_->EnqueueCommand(hci::ReadPageTimeoutBuilder::Create(),
121 common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), handler_);
122 }
123
Stop()124 void neighbor::PageModule::impl::Stop() {
125 LOG_DEBUG("Page scan interval:%hd window:%hd", scan_parameters_.interval, scan_parameters_.window);
126 LOG_DEBUG("Page scan_type:%s", hci::PageScanTypeText(scan_type_).c_str());
127 }
128
SetScanActivity(ScanParameters params)129 void neighbor::PageModule::impl::SetScanActivity(ScanParameters params) {
130 hci_layer_->EnqueueCommand(hci::WritePageScanActivityBuilder::Create(params.interval, params.window),
131 common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), handler_);
132
133 hci_layer_->EnqueueCommand(hci::ReadPageScanActivityBuilder::Create(),
134 common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), handler_);
135 LOG_DEBUG("Set page scan activity interval:0x%x/%.02fms window:0x%x/%.02fms", params.interval,
136 ScanIntervalTimeMs(params.interval), params.window, ScanWindowTimeMs(params.window));
137 }
138
GetScanActivity() const139 ScanParameters neighbor::PageModule::impl::GetScanActivity() const {
140 return scan_parameters_;
141 }
142
SetScanType(hci::PageScanType scan_type)143 void neighbor::PageModule::impl::SetScanType(hci::PageScanType scan_type) {
144 hci_layer_->EnqueueCommand(hci::WritePageScanTypeBuilder::Create(scan_type),
145 common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), handler_);
146
147 hci_layer_->EnqueueCommand(hci::ReadPageScanTypeBuilder::Create(),
148 common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), handler_);
149 LOG_DEBUG("Set page scan type:%s", hci::PageScanTypeText(scan_type).c_str());
150 }
151
SetTimeout(PageTimeout timeout)152 void neighbor::PageModule::impl::SetTimeout(PageTimeout timeout) {
153 hci_layer_->EnqueueCommand(hci::WritePageTimeoutBuilder::Create(timeout),
154 common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), handler_);
155
156 hci_layer_->EnqueueCommand(hci::ReadPageTimeoutBuilder::Create(),
157 common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), handler_);
158 LOG_DEBUG("Set page scan timeout:0x%x/%.02fms", timeout, PageTimeoutMs(timeout));
159 }
160
161 /**
162 * General API here
163 */
PageModule()164 neighbor::PageModule::PageModule() : pimpl_(std::make_unique<impl>(*this)) {}
165
~PageModule()166 neighbor::PageModule::~PageModule() {
167 pimpl_.reset();
168 }
169
SetScanActivity(ScanParameters params)170 void neighbor::PageModule::SetScanActivity(ScanParameters params) {
171 pimpl_->SetScanActivity(params);
172 }
173
GetScanActivity() const174 ScanParameters neighbor::PageModule::GetScanActivity() const {
175 return pimpl_->GetScanActivity();
176 }
177
SetInterlacedScan()178 void neighbor::PageModule::SetInterlacedScan() {
179 pimpl_->SetScanType(hci::PageScanType::INTERLACED);
180 }
181
SetStandardScan()182 void neighbor::PageModule::SetStandardScan() {
183 pimpl_->SetScanType(hci::PageScanType::STANDARD);
184 }
185
SetTimeout(PageTimeout timeout)186 void neighbor::PageModule::SetTimeout(PageTimeout timeout) {
187 pimpl_->SetTimeout(timeout);
188 }
189
190 /**
191 * Module methods here
192 */
ListDependencies(ModuleList * list)193 void neighbor::PageModule::ListDependencies(ModuleList* list) {
194 list->add<hci::HciLayer>();
195 }
196
Start()197 void neighbor::PageModule::Start() {
198 pimpl_->Start();
199 }
200
Stop()201 void neighbor::PageModule::Stop() {
202 pimpl_->Stop();
203 }
204
205 } // namespace neighbor
206 } // namespace bluetooth
207