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 <climits>
18
19 #include "pw_bluetooth_sapphire/internal/host/common/assert.h"
20 #include "pw_string/format.h"
21
22 #pragma clang diagnostic ignored "-Wswitch-enum"
23
24 namespace bt {
25 namespace {
26
TypeToString(DeviceAddress::Type type)27 std::string TypeToString(DeviceAddress::Type type) {
28 switch (type) {
29 case DeviceAddress::Type::kBREDR:
30 return "(BD_ADDR) ";
31 case DeviceAddress::Type::kLEPublic:
32 return "(LE publ) ";
33 case DeviceAddress::Type::kLERandom:
34 return "(LE rand) ";
35 case DeviceAddress::Type::kLEAnonymous:
36 return "(LE anon) ";
37 }
38
39 return "(invalid) ";
40 }
41
42 } // namespace
43
DeviceAddressBytes()44 DeviceAddressBytes::DeviceAddressBytes() { SetToZero(); }
45
DeviceAddressBytes(std::array<uint8_t,kDeviceAddressSize> bytes)46 DeviceAddressBytes::DeviceAddressBytes(
47 std::array<uint8_t, kDeviceAddressSize> bytes) {
48 bytes_ = bytes;
49 }
50
DeviceAddressBytes(const ByteBuffer & bytes)51 DeviceAddressBytes::DeviceAddressBytes(const ByteBuffer& bytes) {
52 BT_DEBUG_ASSERT(bytes.size() == bytes_.size());
53 std::copy(bytes.cbegin(), bytes.cend(), bytes_.begin());
54 }
55
DeviceAddressBytes(pw::bluetooth::emboss::BdAddrView view)56 DeviceAddressBytes::DeviceAddressBytes(pw::bluetooth::emboss::BdAddrView view) {
57 pw::bluetooth::emboss::MakeBdAddrView(&bytes_).CopyFrom(view);
58 }
59
ToString() const60 std::string DeviceAddressBytes::ToString() const {
61 constexpr size_t out_size = sizeof("00:00:00:00:00:00");
62 char out[out_size] = "";
63 // Ignore errors. If an error occurs, an empty string will be returned.
64 pw::StatusWithSize result =
65 pw::string::Format({out, sizeof(out)},
66 "%02X:%02X:%02X:%02X:%02X:%02X",
67 bytes_[5],
68 bytes_[4],
69 bytes_[3],
70 bytes_[2],
71 bytes_[1],
72 bytes_[0]);
73 BT_DEBUG_ASSERT(result.ok());
74 return out;
75 }
76
SetToZero()77 void DeviceAddressBytes::SetToZero() { bytes_.fill(0); }
78
Hash() const79 std::size_t DeviceAddressBytes::Hash() const {
80 uint64_t bytes_as_int = 0;
81 int shift_amount = 0;
82 for (const uint8_t& byte : bytes_) {
83 bytes_as_int |= (static_cast<uint64_t>(byte) << shift_amount);
84 shift_amount += 8;
85 }
86
87 std::hash<uint64_t> hash_func;
88 return hash_func(bytes_as_int);
89 }
90
DeviceAddress()91 DeviceAddress::DeviceAddress() : type_(Type::kBREDR) {}
92
DeviceAddress(Type type,const DeviceAddressBytes & value)93 DeviceAddress::DeviceAddress(Type type, const DeviceAddressBytes& value)
94 : type_(type), value_(value) {}
95
DeviceAddress(Type type,std::array<uint8_t,kDeviceAddressSize> bytes)96 DeviceAddress::DeviceAddress(Type type,
97 std::array<uint8_t, kDeviceAddressSize> bytes)
98 : DeviceAddress(type, DeviceAddressBytes(bytes)) {}
99
DeviceAddrToLePeerAddr(Type type)100 pw::bluetooth::emboss::LEPeerAddressType DeviceAddress::DeviceAddrToLePeerAddr(
101 Type type) {
102 switch (type) {
103 case DeviceAddress::Type::kBREDR: {
104 BT_PANIC("BR/EDR address not convertible to LE address");
105 }
106 case DeviceAddress::Type::kLEPublic: {
107 return pw::bluetooth::emboss::LEPeerAddressType::PUBLIC;
108 }
109 case DeviceAddress::Type::kLERandom: {
110 return pw::bluetooth::emboss::LEPeerAddressType::RANDOM;
111 }
112 case DeviceAddress::Type::kLEAnonymous: {
113 return pw::bluetooth::emboss::LEPeerAddressType::ANONYMOUS;
114 }
115 default: {
116 BT_PANIC("invalid DeviceAddressType");
117 }
118 }
119 }
120
LePeerAddrToDeviceAddr(pw::bluetooth::emboss::LEPeerAddressType type)121 DeviceAddress::Type DeviceAddress::LePeerAddrToDeviceAddr(
122 pw::bluetooth::emboss::LEPeerAddressType type) {
123 switch (type) {
124 case pw::bluetooth::emboss::LEPeerAddressType::PUBLIC: {
125 return DeviceAddress::Type::kLEPublic;
126 }
127 case pw::bluetooth::emboss::LEPeerAddressType::RANDOM: {
128 return DeviceAddress::Type::kLERandom;
129 }
130 case pw::bluetooth::emboss::LEPeerAddressType::ANONYMOUS: {
131 return DeviceAddress::Type::kLEAnonymous;
132 }
133 default: {
134 BT_PANIC("invalid LEPeerAddressType");
135 }
136 }
137 }
138
DeviceAddrToLeAddr(DeviceAddress::Type type)139 pw::bluetooth::emboss::LEAddressType DeviceAddress::DeviceAddrToLeAddr(
140 DeviceAddress::Type type) {
141 switch (type) {
142 case DeviceAddress::Type::kLEPublic: {
143 return pw::bluetooth::emboss::LEAddressType::PUBLIC;
144 }
145 case DeviceAddress::Type::kLERandom: {
146 return pw::bluetooth::emboss::LEAddressType::RANDOM;
147 }
148 default: {
149 BT_PANIC("invalid DeviceAddressType");
150 }
151 }
152 }
153
LeAddrToDeviceAddr(pw::bluetooth::emboss::LEAddressType type)154 DeviceAddress::Type DeviceAddress::LeAddrToDeviceAddr(
155 pw::bluetooth::emboss::LEAddressType type) {
156 switch (type) {
157 case pw::bluetooth::emboss::LEAddressType::PUBLIC:
158 case pw::bluetooth::emboss::LEAddressType::PUBLIC_IDENTITY: {
159 return DeviceAddress::Type::kLEPublic;
160 }
161 case pw::bluetooth::emboss::LEAddressType::RANDOM:
162 case pw::bluetooth::emboss::LEAddressType::RANDOM_IDENTITY: {
163 return DeviceAddress::Type::kLERandom;
164 }
165 default: {
166 BT_PANIC("invalid LEAddressType");
167 }
168 }
169 }
170
IsResolvablePrivate() const171 bool DeviceAddress::IsResolvablePrivate() const {
172 // "The two most significant bits of [a RPA] shall be equal to 0 and 1".
173 // (Vol 6, Part B, 1.3.2.2).
174 uint8_t msb = value_.bytes()[5];
175 return type_ == Type::kLERandom && (msb & 0b01000000) && (~msb & 0b10000000);
176 }
177
IsNonResolvablePrivate() const178 bool DeviceAddress::IsNonResolvablePrivate() const {
179 // "The two most significant bits of [a NRPA] shall be equal to 0".
180 // (Vol 6, Part B, 1.3.2.2).
181 uint8_t msb = value_.bytes()[5];
182 return type_ == Type::kLERandom && !(msb & 0b11000000);
183 }
184
IsStaticRandom() const185 bool DeviceAddress::IsStaticRandom() const {
186 // "The two most significant bits of [a static random address] shall be equal
187 // to 1". (Vol 6, Part B, 1.3.2.1).
188 uint8_t msb = value_.bytes()[5];
189 return type_ == Type::kLERandom && ((msb & 0b11000000) == 0b11000000);
190 }
191
Hash() const192 std::size_t DeviceAddress::Hash() const {
193 const Type type_for_hashing = IsPublic() ? Type::kBREDR : type_;
194 std::size_t const h1(std::hash<Type>{}(type_for_hashing));
195 std::size_t h2 = value_.Hash();
196
197 return h1 ^ (h2 << 1);
198 }
199
ToString() const200 std::string DeviceAddress::ToString() const {
201 return TypeToString(type_) + value_.ToString();
202 }
203
204 } // namespace bt
205
206 namespace std {
207
operator ()(argument_type const & value) const208 hash<bt::DeviceAddress>::result_type hash<bt::DeviceAddress>::operator()(
209 argument_type const& value) const {
210 return value.Hash();
211 }
212
213 } // namespace std
214