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 58 const ModuleFactory neighbor::PageModule::Factory = ModuleFactory([]() { return new neighbor::PageModule(); }); 59 60 neighbor::PageModule::impl::impl(neighbor::PageModule& module) : module_(module) {} 61 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 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 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 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 139 ScanParameters neighbor::PageModule::impl::GetScanActivity() const { 140 return scan_parameters_; 141 } 142 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 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 */ 164 neighbor::PageModule::PageModule() : pimpl_(std::make_unique<impl>(*this)) {} 165 166 neighbor::PageModule::~PageModule() { 167 pimpl_.reset(); 168 } 169 170 void neighbor::PageModule::SetScanActivity(ScanParameters params) { 171 pimpl_->SetScanActivity(params); 172 } 173 174 ScanParameters neighbor::PageModule::GetScanActivity() const { 175 return pimpl_->GetScanActivity(); 176 } 177 178 void neighbor::PageModule::SetInterlacedScan() { 179 pimpl_->SetScanType(hci::PageScanType::INTERLACED); 180 } 181 182 void neighbor::PageModule::SetStandardScan() { 183 pimpl_->SetScanType(hci::PageScanType::STANDARD); 184 } 185 186 void neighbor::PageModule::SetTimeout(PageTimeout timeout) { 187 pimpl_->SetTimeout(timeout); 188 } 189 190 /** 191 * Module methods here 192 */ 193 void neighbor::PageModule::ListDependencies(ModuleList* list) { 194 list->add<hci::HciLayer>(); 195 } 196 197 void neighbor::PageModule::Start() { 198 pimpl_->Start(); 199 } 200 201 void neighbor::PageModule::Stop() { 202 pimpl_->Stop(); 203 } 204 205 } // namespace neighbor 206 } // namespace bluetooth 207