1 // Copyright 2023 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 15 #include "pw_bluetooth_sapphire/internal/host/hci/advertising_handle_map.h" 16 17 namespace bt::hci { 18 MapHandle(const DeviceAddress & address)19std::optional<hci_spec::AdvertisingHandle> AdvertisingHandleMap::MapHandle( 20 const DeviceAddress& address) { 21 if (auto it = addr_to_handle_.find(address); it != addr_to_handle_.end()) { 22 return it->second; 23 } 24 25 if (Size() >= capacity_) { 26 return std::nullopt; 27 } 28 29 std::optional<hci_spec::AdvertisingHandle> handle = NextHandle(); 30 BT_ASSERT(handle); 31 32 addr_to_handle_[address] = handle.value(); 33 handle_to_addr_[handle.value()] = address; 34 return handle; 35 } 36 37 // Convert a DeviceAddress to an AdvertisingHandle. The conversion may fail if 38 // there is no AdvertisingHandle currently mapping to the provided device 39 // address. GetHandle(const DeviceAddress & address) const40std::optional<hci_spec::AdvertisingHandle> AdvertisingHandleMap::GetHandle( 41 const DeviceAddress& address) const { 42 if (auto it = addr_to_handle_.find(address); it != addr_to_handle_.end()) { 43 return it->second; 44 } 45 46 return std::nullopt; 47 } 48 GetAddress(hci_spec::AdvertisingHandle handle) const49std::optional<DeviceAddress> AdvertisingHandleMap::GetAddress( 50 hci_spec::AdvertisingHandle handle) const { 51 if (handle_to_addr_.count(handle) != 0) { 52 return handle_to_addr_.at(handle); 53 } 54 55 return std::nullopt; 56 } 57 RemoveHandle(hci_spec::AdvertisingHandle handle)58void AdvertisingHandleMap::RemoveHandle(hci_spec::AdvertisingHandle handle) { 59 if (handle_to_addr_.count(handle) == 0) { 60 return; 61 } 62 63 const DeviceAddress& address = handle_to_addr_[handle]; 64 addr_to_handle_.erase(address); 65 handle_to_addr_.erase(handle); 66 } 67 RemoveAddress(const DeviceAddress & address)68void AdvertisingHandleMap::RemoveAddress(const DeviceAddress& address) { 69 auto node = addr_to_handle_.extract(address); 70 if (node.empty()) { 71 return; 72 } 73 74 hci_spec::AdvertisingHandle handle = node.mapped(); 75 handle_to_addr_.erase(handle); 76 } 77 Size() const78std::size_t AdvertisingHandleMap::Size() const { 79 BT_ASSERT(addr_to_handle_.size() == handle_to_addr_.size()); 80 return addr_to_handle_.size(); 81 } 82 Empty() const83bool AdvertisingHandleMap::Empty() const { 84 BT_ASSERT(addr_to_handle_.empty() == handle_to_addr_.empty()); 85 return addr_to_handle_.empty(); 86 } 87 Clear()88void AdvertisingHandleMap::Clear() { 89 last_handle_ = kStartHandle; 90 addr_to_handle_.clear(); 91 handle_to_addr_.clear(); 92 } 93 NextHandle()94std::optional<hci_spec::AdvertisingHandle> AdvertisingHandleMap::NextHandle() { 95 if (Size() >= capacity_) { 96 return std::nullopt; 97 } 98 99 hci_spec::AdvertisingHandle handle = last_handle_; 100 do { 101 handle = static_cast<uint8_t>(handle + 1) % capacity_; 102 } while (handle_to_addr_.count(handle) != 0); 103 104 last_handle_ = handle; 105 return handle; 106 } 107 108 std::optional<hci_spec::AdvertisingHandle> LastUsedHandleForTesting() const109AdvertisingHandleMap::LastUsedHandleForTesting() const { 110 if (last_handle_ > hci_spec::kMaxAdvertisingHandle) { 111 return std::nullopt; 112 } 113 114 return last_handle_; 115 } 116 } // namespace bt::hci 117