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