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 #pragma once 16 #include <pw_bluetooth/hci_common.emb.h> 17 18 #include <array> 19 #include <initializer_list> 20 #include <optional> 21 #include <string> 22 23 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h" 24 25 namespace bt { 26 27 const size_t kDeviceAddressSize = 6; 28 29 // Represents a 48-bit BD_ADDR. This data structure can be directly serialized 30 // into HCI command payloads. 31 class DeviceAddressBytes { 32 public: 33 // The default constructor initializes the address to 00:00:00:00:00:00. 34 DeviceAddressBytes(); 35 36 // Initializes the contents from |bytes|. 37 explicit DeviceAddressBytes(std::array<uint8_t, kDeviceAddressSize> bytes); 38 explicit DeviceAddressBytes(const ByteBuffer& bytes); 39 explicit DeviceAddressBytes(pw::bluetooth::emboss::BdAddrView view); 40 41 // Returns a string representation of the device address. The bytes in 42 // human-readable form will appear in big-endian byte order even though the 43 // underlying array stores the bytes in little-endian. The returned string 44 // will be of the form: 45 // 46 // XX:XX:XX:XX:XX:XX 47 std::string ToString() const; 48 49 // Sets all bits of the BD_ADDR to 0. 50 void SetToZero(); 51 52 // Returns a view over the raw bytes of this address. bytes()53 BufferView bytes() const { return BufferView(bytes_.data(), bytes_.size()); } 54 55 // Comparison operators. 56 bool operator==(const DeviceAddressBytes& other) const { 57 return bytes_ == other.bytes_; 58 } 59 bool operator!=(const DeviceAddressBytes& other) const { 60 return !(*this == other); 61 } 62 bool operator<(const DeviceAddressBytes& other) const { 63 return bytes_ < other.bytes_; 64 } 65 view()66 pw::bluetooth::emboss::BdAddrView view() const { 67 return pw::bluetooth::emboss::MakeBdAddrView(&bytes_); 68 } 69 70 // Returns a hash of the contents of this address. 71 std::size_t Hash() const; 72 73 private: 74 // The raw bytes of the BD_ADDR stored in little-endian byte order. 75 std::array<uint8_t, kDeviceAddressSize> bytes_; 76 }; 77 78 static_assert(sizeof(DeviceAddressBytes) == 6, 79 "DeviceAddressBytes must take up exactly 6 bytes"); 80 81 // DeviceAddress represents a Bluetooth device address, encapsulating the 48-bit 82 // device address and the address type. A DeviceAddress is comparable and can be 83 // used as a key in ordered and unordered associative STL containers. 84 // 85 // TODO(fxbug.dev/42102158): Using the underlying DeviceAddressBytes for 86 // equality, comparison, and hashing effectively obsoletes DeviceAddressBytes as 87 // a separate class. Removing the |type_| field (see bug for rationale) will 88 // make this class compatible with serialization. 89 class DeviceAddress { 90 public: 91 // Bluetooth device address types. 92 enum class Type : uint16_t { 93 // BD_ADDR as used in Bluetooth Classic. 94 kBREDR, 95 96 // Low Energy Address types. 97 kLEPublic, 98 kLERandom, 99 kLEAnonymous, 100 }; 101 102 // Utilities to convert between DeviceAddress::Type and the LE peer address 103 // type. 104 static pw::bluetooth::emboss::LEAddressType DeviceAddrToLeAddr(Type type); 105 static pw::bluetooth::emboss::LEPeerAddressType DeviceAddrToLePeerAddr( 106 Type type); 107 static pw::bluetooth::emboss::LEPeerAddressTypeNoAnon 108 DeviceAddrToLePeerAddrNoAnon(Type type); 109 static pw::bluetooth::emboss::LEOwnAddressType DeviceAddrToLEOwnAddr( 110 Type type); 111 112 static Type LeAddrToDeviceAddr(pw::bluetooth::emboss::LEAddressType type); 113 static Type LeAddrToDeviceAddr(pw::bluetooth::emboss::LEPeerAddressType type); 114 static Type LeAddrToDeviceAddr( 115 pw::bluetooth::emboss::LEPeerAddressTypeNoAnon type); 116 static std::optional<Type> LeAddrToDeviceAddr( 117 pw::bluetooth::emboss::LEExtendedAddressType type); 118 119 // The default constructor initializes the address to 00:00:00:00:00:00 and 120 // the type to Type::kBREDR. 121 DeviceAddress(); 122 123 // Initializes the contents from raw data. 124 DeviceAddress(Type type, const DeviceAddressBytes& value); 125 DeviceAddress(Type type, std::array<uint8_t, kDeviceAddressSize> bytes); 126 type()127 Type type() const { return type_; } value()128 const DeviceAddressBytes& value() const { return value_; } 129 IsBrEdr()130 bool IsBrEdr() const { return type_ == Type::kBREDR; } IsLowEnergy()131 bool IsLowEnergy() const { 132 return type_ == Type::kLEPublic || type_ == Type::kLERandom || 133 type_ == Type::kLEAnonymous; 134 } 135 136 // Comparison operators. The equality and less-than operators are needed to 137 // support unordered and ordered containers, respectively. 138 bool operator==(const DeviceAddress& other) const { 139 return IsTypeCompatible(other) && value_ == other.value_; 140 } 141 bool operator!=(const DeviceAddress& other) const { 142 return !(*this == other); 143 } 144 bool operator<(const DeviceAddress& other) const { 145 // Treat |type_| as the higher-order bits 146 if (type_ < other.type_ && !IsTypeCompatible(other)) { 147 return true; 148 } 149 return IsTypeCompatible(other) && value_ < other.value_; 150 } 151 152 // Returns true if this address is a BR/EDR BD_ADDR or LE public address. IsPublic()153 bool IsPublic() const { 154 return type_ == Type::kBREDR || type_ == Type::kLEPublic; 155 } 156 157 // Returns true if this address is a Resolvable Private Address. 158 bool IsResolvablePrivate() const; 159 160 // Returns true if this address is a Non-resolvable Private Address. 161 bool IsNonResolvablePrivate() const; 162 163 // Returns true if this is a static random device address. 164 bool IsStaticRandom() const; 165 166 // Returns a hash of the contents of this address. 167 std::size_t Hash() const; 168 169 // Returns a string representation of this address. 170 std::string ToString() const; 171 172 private: 173 // True if both addresses have types indicating they're used for the same 174 // purpose IsTypeCompatible(const DeviceAddress & other)175 bool IsTypeCompatible(const DeviceAddress& other) const { 176 return (type_ == other.type_) || (IsPublic() && other.IsPublic()); 177 } 178 179 Type type_; 180 DeviceAddressBytes value_; 181 }; 182 183 static_assert(sizeof(DeviceAddress) == 8, 184 "DeviceAddress must take up exactly 8 bytes"); 185 186 } // namespace bt 187 188 // Custom specialization of std::hash to support unordered associative 189 // containers. 190 namespace std { 191 192 template <> 193 struct hash<bt::DeviceAddress> { 194 using argument_type = bt::DeviceAddress; 195 using result_type = std::size_t; 196 197 result_type operator()(argument_type const& value) const; 198 }; 199 200 } // namespace std 201