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