xref: /aosp_15_r20/external/pigweed/pw_bluetooth_sapphire/host/hci/advertising_handle_map.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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,bool extended_pdu)19 std::optional<hci_spec::AdvertisingHandle> AdvertisingHandleMap::MapHandle(
20     const DeviceAddress& address, bool extended_pdu) {
21   if (auto it = addr_to_handle_.find({address, extended_pdu});
22       it != addr_to_handle_.end()) {
23     return it->second;
24   }
25 
26   if (Size() >= capacity_) {
27     return std::nullopt;
28   }
29 
30   std::optional<hci_spec::AdvertisingHandle> handle = NextHandle();
31   PW_CHECK(handle);
32 
33   addr_to_handle_[{address, extended_pdu}] = handle.value();
34   handle_to_addr_[handle.value()] = {address, extended_pdu};
35   return handle;
36 }
37 
38 // Convert a DeviceAddress to an AdvertisingHandle. The conversion may fail if
39 // there is no AdvertisingHandle currently mapping to the provided device
40 // address.
GetHandle(const DeviceAddress & address,bool extended_pdu) const41 std::optional<hci_spec::AdvertisingHandle> AdvertisingHandleMap::GetHandle(
42     const DeviceAddress& address, bool extended_pdu) const {
43   if (auto it = addr_to_handle_.find({address, extended_pdu});
44       it != addr_to_handle_.end()) {
45     return it->second;
46   }
47 
48   return std::nullopt;
49 }
50 
GetAddress(hci_spec::AdvertisingHandle handle) const51 std::optional<DeviceAddress> AdvertisingHandleMap::GetAddress(
52     hci_spec::AdvertisingHandle handle) const {
53   if (handle_to_addr_.count(handle) != 0) {
54     const auto& [address, extended] = handle_to_addr_.at(handle);
55     return address;
56   }
57 
58   return std::nullopt;
59 }
60 
RemoveHandle(hci_spec::AdvertisingHandle handle)61 void AdvertisingHandleMap::RemoveHandle(hci_spec::AdvertisingHandle handle) {
62   if (handle_to_addr_.count(handle) == 0) {
63     return;
64   }
65 
66   const auto& [address, extended] = handle_to_addr_[handle];
67   addr_to_handle_.erase({address, extended});
68   handle_to_addr_.erase(handle);
69 }
70 
RemoveAddress(const DeviceAddress & address,bool extended)71 void AdvertisingHandleMap::RemoveAddress(const DeviceAddress& address,
72                                          bool extended) {
73   auto node = addr_to_handle_.extract({address, extended});
74   if (node.empty()) {
75     return;
76   }
77 
78   hci_spec::AdvertisingHandle handle = node.mapped();
79   handle_to_addr_.erase(handle);
80 }
81 
Size() const82 std::size_t AdvertisingHandleMap::Size() const {
83   PW_CHECK(addr_to_handle_.size() == handle_to_addr_.size());
84   return addr_to_handle_.size();
85 }
86 
Empty() const87 bool AdvertisingHandleMap::Empty() const {
88   PW_CHECK(addr_to_handle_.empty() == handle_to_addr_.empty());
89   return addr_to_handle_.empty();
90 }
91 
Clear()92 void AdvertisingHandleMap::Clear() {
93   last_handle_ = kStartHandle;
94   addr_to_handle_.clear();
95   handle_to_addr_.clear();
96 }
97 
NextHandle()98 std::optional<hci_spec::AdvertisingHandle> AdvertisingHandleMap::NextHandle() {
99   if (Size() >= capacity_) {
100     return std::nullopt;
101   }
102 
103   hci_spec::AdvertisingHandle handle = last_handle_;
104   do {
105     handle = static_cast<uint8_t>(handle + 1) % capacity_;
106   } while (handle_to_addr_.count(handle) != 0);
107 
108   last_handle_ = handle;
109   return handle;
110 }
111 
112 std::optional<hci_spec::AdvertisingHandle>
LastUsedHandleForTesting() const113 AdvertisingHandleMap::LastUsedHandleForTesting() const {
114   if (last_handle_ > hci_spec::kMaxAdvertisingHandle) {
115     return std::nullopt;
116   }
117 
118   return last_handle_;
119 }
120 }  // namespace bt::hci
121