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