• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)19 std::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) const40 std::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) const49 std::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)58 void 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)68 void 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() const78 std::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() const83 bool AdvertisingHandleMap::Empty() const {
84   BT_ASSERT(addr_to_handle_.empty() == handle_to_addr_.empty());
85   return addr_to_handle_.empty();
86 }
87 
Clear()88 void AdvertisingHandleMap::Clear() {
89   last_handle_ = kStartHandle;
90   addr_to_handle_.clear();
91   handle_to_addr_.clear();
92 }
93 
NextHandle()94 std::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() const109 AdvertisingHandleMap::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