• 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 <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