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