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/scan.h" 19 #include <memory> 20 #include "hci/hci_layer.h" 21 #include "hci/hci_packets.h" 22 #include "module.h" 23 #include "os/handler.h" 24 #include "os/log.h" 25 26 namespace bluetooth { 27 namespace neighbor { 28 29 struct ScanModule::impl { 30 impl(ScanModule& module); 31 32 void SetInquiryScan(bool enabled); 33 bool IsInquiryEnabled() const; 34 35 void SetPageScan(bool enabled); 36 bool IsPageEnabled() const; 37 38 void Start(); 39 void Stop(); 40 41 private: 42 ScanModule& module_; 43 44 bool inquiry_scan_enabled_; 45 bool page_scan_enabled_; 46 47 void WriteScanEnable(); 48 void ReadScanEnable(hci::ScanEnable); 49 50 void OnCommandComplete(hci::CommandCompleteView status); 51 52 hci::HciLayer* hci_layer_; 53 os::Handler* handler_; 54 }; 55 56 const ModuleFactory neighbor::ScanModule::Factory = ModuleFactory([]() { return new neighbor::ScanModule(); }); 57 58 neighbor::ScanModule::impl::impl(neighbor::ScanModule& module) 59 : module_(module), inquiry_scan_enabled_(false), page_scan_enabled_(false) {} 60 61 void neighbor::ScanModule::impl::OnCommandComplete(hci::CommandCompleteView view) { 62 switch (view.GetCommandOpCode()) { 63 case hci::OpCode::READ_SCAN_ENABLE: { 64 auto packet = hci::ReadScanEnableCompleteView::Create(view); 65 ASSERT(packet.IsValid()); 66 ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS); 67 ReadScanEnable(packet.GetScanEnable()); 68 } break; 69 70 case hci::OpCode::WRITE_SCAN_ENABLE: { 71 auto packet = hci::WriteScanEnableCompleteView::Create(view); 72 ASSERT(packet.IsValid()); 73 ASSERT(packet.GetStatus() == hci::ErrorCode::SUCCESS); 74 } break; 75 76 default: 77 LOG_ERROR("Unhandled command %s", hci::OpCodeText(view.GetCommandOpCode()).c_str()); 78 break; 79 } 80 } 81 82 void neighbor::ScanModule::impl::WriteScanEnable() { 83 hci::ScanEnable scan_enable; 84 85 if (inquiry_scan_enabled_ && !page_scan_enabled_) { 86 scan_enable = hci::ScanEnable::INQUIRY_SCAN_ONLY; 87 } else if (!inquiry_scan_enabled_ && page_scan_enabled_) { 88 scan_enable = hci::ScanEnable::PAGE_SCAN_ONLY; 89 } else if (inquiry_scan_enabled_ && page_scan_enabled_) { 90 scan_enable = hci::ScanEnable::INQUIRY_AND_PAGE_SCAN; 91 } else { 92 scan_enable = hci::ScanEnable::NO_SCANS; 93 } 94 95 { 96 std::unique_ptr<hci::WriteScanEnableBuilder> packet = hci::WriteScanEnableBuilder::Create(scan_enable); 97 hci_layer_->EnqueueCommand(std::move(packet), common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), 98 handler_); 99 } 100 101 { 102 std::unique_ptr<hci::ReadScanEnableBuilder> packet = hci::ReadScanEnableBuilder::Create(); 103 hci_layer_->EnqueueCommand(std::move(packet), common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), 104 handler_); 105 } 106 } 107 108 void neighbor::ScanModule::impl::ReadScanEnable(hci::ScanEnable scan_enable) { 109 switch (scan_enable) { 110 case hci::ScanEnable::INQUIRY_SCAN_ONLY: 111 inquiry_scan_enabled_ = true; 112 page_scan_enabled_ = false; 113 break; 114 115 case hci::ScanEnable::PAGE_SCAN_ONLY: 116 inquiry_scan_enabled_ = false; 117 page_scan_enabled_ = true; 118 break; 119 120 case hci::ScanEnable::INQUIRY_AND_PAGE_SCAN: 121 inquiry_scan_enabled_ = true; 122 page_scan_enabled_ = true; 123 break; 124 125 default: 126 inquiry_scan_enabled_ = false; 127 page_scan_enabled_ = false; 128 break; 129 } 130 } 131 132 void neighbor::ScanModule::impl::SetInquiryScan(bool enabled) { 133 inquiry_scan_enabled_ = enabled; 134 WriteScanEnable(); 135 } 136 137 void neighbor::ScanModule::impl::SetPageScan(bool enabled) { 138 page_scan_enabled_ = enabled; 139 WriteScanEnable(); 140 } 141 142 bool neighbor::ScanModule::impl::IsInquiryEnabled() const { 143 return inquiry_scan_enabled_; 144 } 145 146 bool neighbor::ScanModule::impl::IsPageEnabled() const { 147 return page_scan_enabled_; 148 } 149 150 void neighbor::ScanModule::impl::Start() { 151 hci_layer_ = module_.GetDependency<hci::HciLayer>(); 152 handler_ = module_.GetHandler(); 153 154 std::unique_ptr<hci::ReadScanEnableBuilder> packet = hci::ReadScanEnableBuilder::Create(); 155 hci_layer_->EnqueueCommand(std::move(packet), common::BindOnce(&impl::OnCommandComplete, common::Unretained(this)), 156 handler_); 157 } 158 159 void neighbor::ScanModule::impl::Stop() { 160 LOG_DEBUG("inquiry scan enabled:%d page scan enabled:%d", inquiry_scan_enabled_, page_scan_enabled_); 161 } 162 163 neighbor::ScanModule::ScanModule() : pimpl_(std::make_unique<impl>(*this)) {} 164 165 neighbor::ScanModule::~ScanModule() { 166 pimpl_.reset(); 167 } 168 169 void neighbor::ScanModule::SetInquiryScan() { 170 pimpl_->SetInquiryScan(true); 171 } 172 173 void neighbor::ScanModule::ClearInquiryScan() { 174 pimpl_->SetInquiryScan(false); 175 } 176 177 void neighbor::ScanModule::SetPageScan() { 178 pimpl_->SetPageScan(true); 179 } 180 181 void neighbor::ScanModule::ClearPageScan() { 182 pimpl_->SetPageScan(false); 183 } 184 185 bool neighbor::ScanModule::IsInquiryEnabled() const { 186 return pimpl_->IsInquiryEnabled(); 187 } 188 189 bool neighbor::ScanModule::IsPageEnabled() const { 190 return pimpl_->IsPageEnabled(); 191 } 192 193 void neighbor::ScanModule::ListDependencies(ModuleList* list) { 194 list->add<hci::HciLayer>(); 195 } 196 197 void neighbor::ScanModule::Start() { 198 pimpl_->Start(); 199 } 200 201 void neighbor::ScanModule::Stop() { 202 pimpl_->Stop(); 203 } 204 205 } // namespace neighbor 206 } // namespace bluetooth 207