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