xref: /aosp_15_r20/external/pigweed/pw_bluetooth_sapphire/host/common/device_address.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/common/device_address.h"
16 
17 #include "pw_bluetooth_sapphire/internal/host/common/assert.h"
18 #include "pw_preprocessor/compiler.h"
19 #include "pw_string/format.h"
20 
21 namespace bt {
22 namespace {
23 
TypeToString(DeviceAddress::Type type)24 std::string TypeToString(DeviceAddress::Type type) {
25   switch (type) {
26     case DeviceAddress::Type::kBREDR:
27       return "(BD_ADDR) ";
28     case DeviceAddress::Type::kLEPublic:
29       return "(LE publ) ";
30     case DeviceAddress::Type::kLERandom:
31       return "(LE rand) ";
32     case DeviceAddress::Type::kLEAnonymous:
33       return "(LE anon) ";
34   }
35 
36   return "(invalid) ";
37 }
38 
39 }  // namespace
40 
DeviceAddressBytes()41 DeviceAddressBytes::DeviceAddressBytes() { SetToZero(); }
42 
DeviceAddressBytes(std::array<uint8_t,kDeviceAddressSize> bytes)43 DeviceAddressBytes::DeviceAddressBytes(
44     std::array<uint8_t, kDeviceAddressSize> bytes) {
45   bytes_ = bytes;
46 }
47 
DeviceAddressBytes(const ByteBuffer & bytes)48 DeviceAddressBytes::DeviceAddressBytes(const ByteBuffer& bytes) {
49   PW_DCHECK(bytes.size() == bytes_.size());
50   std::copy(bytes.cbegin(), bytes.cend(), bytes_.begin());
51 }
52 
DeviceAddressBytes(pw::bluetooth::emboss::BdAddrView view)53 DeviceAddressBytes::DeviceAddressBytes(pw::bluetooth::emboss::BdAddrView view) {
54   pw::bluetooth::emboss::MakeBdAddrView(&bytes_).CopyFrom(view);
55 }
56 
ToString() const57 std::string DeviceAddressBytes::ToString() const {
58   constexpr size_t out_size = sizeof("00:00:00:00:00:00");
59   char out[out_size] = "";
60   // Ignore errors. If an error occurs, an empty string will be returned.
61   pw::StatusWithSize result =
62       pw::string::Format({out, sizeof(out)},
63                          "%02X:%02X:%02X:%02X:%02X:%02X",
64                          bytes_[5],
65                          bytes_[4],
66                          bytes_[3],
67                          bytes_[2],
68                          bytes_[1],
69                          bytes_[0]);
70   PW_DCHECK(result.ok());
71   return out;
72 }
73 
SetToZero()74 void DeviceAddressBytes::SetToZero() { bytes_.fill(0); }
75 
Hash() const76 std::size_t DeviceAddressBytes::Hash() const {
77   uint64_t bytes_as_int = 0;
78   int shift_amount = 0;
79   for (const uint8_t& byte : bytes_) {
80     bytes_as_int |= (static_cast<uint64_t>(byte) << shift_amount);
81     shift_amount += 8;
82   }
83 
84   std::hash<uint64_t> hash_func;
85   return hash_func(bytes_as_int);
86 }
87 
DeviceAddress()88 DeviceAddress::DeviceAddress() : type_(Type::kBREDR) {}
89 
DeviceAddress(Type type,const DeviceAddressBytes & value)90 DeviceAddress::DeviceAddress(Type type, const DeviceAddressBytes& value)
91     : type_(type), value_(value) {}
92 
DeviceAddress(Type type,std::array<uint8_t,kDeviceAddressSize> bytes)93 DeviceAddress::DeviceAddress(Type type,
94                              std::array<uint8_t, kDeviceAddressSize> bytes)
95     : DeviceAddress(type, DeviceAddressBytes(bytes)) {}
96 
DeviceAddrToLeAddr(DeviceAddress::Type type)97 pw::bluetooth::emboss::LEAddressType DeviceAddress::DeviceAddrToLeAddr(
98     DeviceAddress::Type type) {
99   PW_MODIFY_DIAGNOSTICS_PUSH();
100   PW_MODIFY_DIAGNOSTIC(ignored, "-Wswitch-enum");
101   switch (type) {
102     case DeviceAddress::Type::kLEPublic: {
103       return pw::bluetooth::emboss::LEAddressType::PUBLIC;
104     }
105     case DeviceAddress::Type::kLERandom: {
106       return pw::bluetooth::emboss::LEAddressType::RANDOM;
107     }
108     default: {
109       BT_PANIC("invalid DeviceAddressType");
110     }
111   }
112   PW_MODIFY_DIAGNOSTICS_POP();
113 }
114 
DeviceAddrToLePeerAddr(Type type)115 pw::bluetooth::emboss::LEPeerAddressType DeviceAddress::DeviceAddrToLePeerAddr(
116     Type type) {
117   switch (type) {
118     case DeviceAddress::Type::kBREDR: {
119       BT_PANIC("BR/EDR address not convertible to LE address");
120     }
121     case DeviceAddress::Type::kLEPublic: {
122       return pw::bluetooth::emboss::LEPeerAddressType::PUBLIC;
123     }
124     case DeviceAddress::Type::kLERandom: {
125       return pw::bluetooth::emboss::LEPeerAddressType::RANDOM;
126     }
127     case DeviceAddress::Type::kLEAnonymous: {
128       return pw::bluetooth::emboss::LEPeerAddressType::ANONYMOUS;
129     }
130     default: {
131       BT_PANIC("invalid DeviceAddressType");
132     }
133   }
134 }
135 
DeviceAddrToLEOwnAddr(Type type)136 pw::bluetooth::emboss::LEOwnAddressType DeviceAddress::DeviceAddrToLEOwnAddr(
137     Type type) {
138   switch (type) {
139     case DeviceAddress::Type::kLERandom: {
140       return pw::bluetooth::emboss::LEOwnAddressType::RANDOM;
141     }
142     case DeviceAddress::Type::kLEPublic: {
143       return pw::bluetooth::emboss::LEOwnAddressType::PUBLIC;
144     }
145     case DeviceAddress::Type::kLEAnonymous:
146     case DeviceAddress::Type::kBREDR:
147     default: {
148       BT_PANIC("invalid DeviceAddressType");
149     }
150   }
151 }
152 
LeAddrToDeviceAddr(pw::bluetooth::emboss::LEAddressType type)153 DeviceAddress::Type DeviceAddress::LeAddrToDeviceAddr(
154     pw::bluetooth::emboss::LEAddressType type) {
155   switch (type) {
156     case pw::bluetooth::emboss::LEAddressType::PUBLIC:
157     case pw::bluetooth::emboss::LEAddressType::PUBLIC_IDENTITY: {
158       return DeviceAddress::Type::kLEPublic;
159     }
160     case pw::bluetooth::emboss::LEAddressType::RANDOM:
161     case pw::bluetooth::emboss::LEAddressType::RANDOM_IDENTITY: {
162       return DeviceAddress::Type::kLERandom;
163     }
164     default: {
165       BT_PANIC("invalid LEAddressType");
166     }
167   }
168 }
169 
LeAddrToDeviceAddr(pw::bluetooth::emboss::LEPeerAddressType type)170 DeviceAddress::Type DeviceAddress::LeAddrToDeviceAddr(
171     pw::bluetooth::emboss::LEPeerAddressType type) {
172   switch (type) {
173     case pw::bluetooth::emboss::LEPeerAddressType::PUBLIC: {
174       return DeviceAddress::Type::kLEPublic;
175     }
176     case pw::bluetooth::emboss::LEPeerAddressType::RANDOM: {
177       return DeviceAddress::Type::kLERandom;
178     }
179     case pw::bluetooth::emboss::LEPeerAddressType::ANONYMOUS: {
180       return DeviceAddress::Type::kLEAnonymous;
181     }
182     default: {
183       BT_PANIC("invalid LEPeerAddressType");
184     }
185   }
186 }
187 
LeAddrToDeviceAddr(pw::bluetooth::emboss::LEPeerAddressTypeNoAnon type)188 DeviceAddress::Type DeviceAddress::LeAddrToDeviceAddr(
189     pw::bluetooth::emboss::LEPeerAddressTypeNoAnon type) {
190   switch (type) {
191     case pw::bluetooth::emboss::LEPeerAddressTypeNoAnon::PUBLIC: {
192       return DeviceAddress::Type::kLEPublic;
193     }
194     case pw::bluetooth::emboss::LEPeerAddressTypeNoAnon::RANDOM: {
195       return DeviceAddress::Type::kLERandom;
196     }
197     default: {
198       BT_PANIC("invalid LEPeerAddressTypeNoAnon");
199     }
200   }
201 }
202 
LeAddrToDeviceAddr(pw::bluetooth::emboss::LEExtendedAddressType type)203 std::optional<DeviceAddress::Type> DeviceAddress::LeAddrToDeviceAddr(
204     pw::bluetooth::emboss::LEExtendedAddressType type) {
205   switch (type) {
206     case pw::bluetooth::emboss::LEExtendedAddressType::PUBLIC:
207     case pw::bluetooth::emboss::LEExtendedAddressType::PUBLIC_IDENTITY: {
208       return DeviceAddress::Type::kLEPublic;
209     }
210     case pw::bluetooth::emboss::LEExtendedAddressType::RANDOM:
211     case pw::bluetooth::emboss::LEExtendedAddressType::RANDOM_IDENTITY: {
212       return DeviceAddress::Type::kLERandom;
213     }
214     case pw::bluetooth::emboss::LEExtendedAddressType::ANONYMOUS: {
215       return DeviceAddress::Type::kLEAnonymous;
216     }
217     default: {
218       return std::nullopt;
219     }
220   }
221 }
222 
IsResolvablePrivate() const223 bool DeviceAddress::IsResolvablePrivate() const {
224   // "The two most significant bits of [a RPA] shall be equal to 0 and 1".
225   // (Vol 6, Part B, 1.3.2.2).
226   uint8_t msb = value_.bytes()[5];
227   return type_ == Type::kLERandom && (msb & 0b01000000) && (~msb & 0b10000000);
228 }
229 
IsNonResolvablePrivate() const230 bool DeviceAddress::IsNonResolvablePrivate() const {
231   // "The two most significant bits of [a NRPA] shall be equal to 0".
232   // (Vol 6, Part B, 1.3.2.2).
233   uint8_t msb = value_.bytes()[5];
234   return type_ == Type::kLERandom && !(msb & 0b11000000);
235 }
236 
IsStaticRandom() const237 bool DeviceAddress::IsStaticRandom() const {
238   // "The two most significant bits of [a static random address] shall be equal
239   // to 1". (Vol 6, Part B, 1.3.2.1).
240   uint8_t msb = value_.bytes()[5];
241   return type_ == Type::kLERandom && ((msb & 0b11000000) == 0b11000000);
242 }
243 
Hash() const244 std::size_t DeviceAddress::Hash() const {
245   const Type type_for_hashing = IsPublic() ? Type::kBREDR : type_;
246   std::size_t const h1(std::hash<Type>{}(type_for_hashing));
247   std::size_t h2 = value_.Hash();
248 
249   return h1 ^ (h2 << 1);
250 }
251 
ToString() const252 std::string DeviceAddress::ToString() const {
253   return TypeToString(type_) + value_.ToString();
254 }
255 
256 }  // namespace bt
257 
258 namespace std {
259 
operator ()(argument_type const & value) const260 hash<bt::DeviceAddress>::result_type hash<bt::DeviceAddress>::operator()(
261     argument_type const& value) const {
262   return value.Hash();
263 }
264 
265 }  // namespace std
266