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