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::LEExtendedAddressType 110 DeviceAddrToLeExtendedAddr(Type type); 111 static pw::bluetooth::emboss::LEOwnAddressType DeviceAddrToLeOwnAddr( 112 Type type); 113 114 static Type LeAddrToDeviceAddr(pw::bluetooth::emboss::LEAddressType type); 115 static Type LeAddrToDeviceAddr(pw::bluetooth::emboss::LEPeerAddressType type); 116 static Type LeAddrToDeviceAddr( 117 pw::bluetooth::emboss::LEPeerAddressTypeNoAnon type); 118 static std::optional<Type> LeAddrToDeviceAddr( 119 pw::bluetooth::emboss::LEExtendedAddressType type); 120 121 // The default constructor initializes the address to 00:00:00:00:00:00 and 122 // the type to Type::kBREDR. 123 DeviceAddress(); 124 125 // Initializes the contents from raw data. 126 DeviceAddress(Type type, const DeviceAddressBytes& value); 127 DeviceAddress(Type type, std::array<uint8_t, kDeviceAddressSize> bytes); 128 type()129 Type type() const { return type_; } value()130 const DeviceAddressBytes& value() const { return value_; } 131 IsBrEdr()132 bool IsBrEdr() const { return type_ == Type::kBREDR; } IsLowEnergy()133 bool IsLowEnergy() const { 134 return type_ == Type::kLEPublic || type_ == Type::kLERandom || 135 type_ == Type::kLEAnonymous; 136 } 137 138 // Comparison operators. The equality and less-than operators are needed to 139 // support unordered and ordered containers, respectively. 140 bool operator==(const DeviceAddress& other) const { 141 return IsTypeCompatible(other) && value_ == other.value_; 142 } 143 bool operator!=(const DeviceAddress& other) const { 144 return !(*this == other); 145 } 146 bool operator<(const DeviceAddress& other) const { 147 // Treat |type_| as the higher-order bits 148 if (type_ < other.type_ && !IsTypeCompatible(other)) { 149 return true; 150 } 151 return IsTypeCompatible(other) && value_ < other.value_; 152 } 153 154 // Returns true if this address is a BR/EDR BD_ADDR or LE public address. IsPublic()155 bool IsPublic() const { 156 return type_ == Type::kBREDR || type_ == Type::kLEPublic; 157 } 158 159 // Returns true if this address is a Resolvable Private Address. 160 bool IsResolvablePrivate() const; 161 162 // Returns true if this address is a Non-resolvable Private Address. 163 bool IsNonResolvablePrivate() const; 164 165 // Returns true if this is a static random device address. 166 bool IsStaticRandom() const; 167 168 // Returns a hash of the contents of this address. 169 std::size_t Hash() const; 170 171 // Returns a string representation of this address. 172 std::string ToString() const; 173 174 private: 175 // True if both addresses have types indicating they're used for the same 176 // purpose IsTypeCompatible(const DeviceAddress & other)177 bool IsTypeCompatible(const DeviceAddress& other) const { 178 return (type_ == other.type_) || (IsPublic() && other.IsPublic()); 179 } 180 181 Type type_; 182 DeviceAddressBytes value_; 183 }; 184 185 static_assert(sizeof(DeviceAddress) == 8, 186 "DeviceAddress must take up exactly 8 bytes"); 187 188 } // namespace bt 189 190 // Custom specialization of std::hash to support unordered associative 191 // containers. 192 namespace std { 193 194 template <> 195 struct hash<bt::DeviceAddress> { 196 using argument_type = bt::DeviceAddress; 197 using result_type = std::size_t; 198 199 result_type operator()(argument_type const& value) const; 200 }; 201 202 } // namespace std 203