xref: /aosp_15_r20/external/pigweed/pw_bluetooth/public/pw_bluetooth/address.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2022 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 #pragma once
15 
16 #include <array>
17 #include <cstdint>
18 
19 #include "pw_assert/assert.h"
20 #include "pw_bluetooth/internal/hex.h"
21 #include "pw_span/span.h"
22 #include "pw_string/string.h"
23 
24 namespace pw::bluetooth {
25 
26 // A 48-bit bluetooth device address (BD_ADDR) in little endian format.
27 // See Core Spec v5.3 Volume 2, Part B, Section 1.2.
28 class Address {
29  public:
30   enum class Type : uint8_t {
31     kPublic,
32     kRandomStatic,
33     kRandomResolvablePrivate,
34     kRandomNonResolvablePrivate,
35   };
36   // String size of a hexadecimal representation of an Address, not including
37   // the null terminator.
38   static constexpr size_t kHexStringSize = 17;
39 
40   // Create an Address from its binary representation.
41   // The first byte in the span is the last one in the hex representation, thus
42   // the BD_ADDR 00:11:22:33:44:55 should be created from the span with bytes:
43   // {0x55, 0x44, 0x33, 0x22, 0x11, 0x00}.
Address(const span<const uint8_t,6> addr_span)44   constexpr Address(const span<const uint8_t, 6> addr_span) : addr_() {
45     static_assert(addr_span.size() == sizeof(addr_));
46     for (size_t i = 0; i < sizeof(addr_); i++) {
47       addr_[i] = addr_span[i];
48     }
49   }
50 
51   // Create an address from the hex format "00:11:22:33:44:55". The passed
52   // string must have a length of 17 and a ":" character on the 3rd, 6th, 9th,
53   // 12th and 15th positions. The hexadecimal representation is such that the
54   // first byte in the string is the last byte in the binary representation.
Address(const char (& str_addr)[kHexStringSize+1])55   constexpr Address(const char (&str_addr)[kHexStringSize + 1]) : addr_() {
56     PW_ASSERT((str_addr[2] == ':') && (str_addr[5] == ':') &&
57               (str_addr[8] == ':') && (str_addr[11] == ':') &&
58               (str_addr[14] == ':'));
59     for (size_t i = 0; i < sizeof(addr_); i++) {
60       uint16_t value = (internal::HexToNibble(str_addr[3 * i]) << 4u) |
61                        internal::HexToNibble(str_addr[3 * i + 1]);
62       addr_[sizeof(addr_) - 1 - i] = value;
63       PW_ASSERT(value <= 0xff);
64     }
65   }
66 
67   // Return the bluetooth address a the 6-byte binary representation.
AsSpan()68   constexpr span<const uint8_t, 6> AsSpan() const {
69     return span<const uint8_t, 6>{addr_.data(), addr_.size()};
70   }
71 
72   // Return an inline pw_string representation of the Address in hexadecimal
73   // using ":" characters as byte separator.
ToString()74   constexpr InlineString<kHexStringSize> ToString() const {
75     InlineString<kHexStringSize> ret;
76     for (size_t i = addr_.size(); i-- != 0;) {
77       ret += internal::NibbleToHex(addr_[i] >> 4);
78       ret += internal::NibbleToHex(addr_[i] & 0xf);
79       if (i) {
80         ret += ':';
81       }
82     }
83     return ret;
84   }
85 
86  private:
87   std::array<uint8_t, 6> addr_;
88 };
89 
90 // Address comparators:
91 constexpr bool operator==(const Address& a, const Address& b) {
92   const auto a_span = a.AsSpan();
93   const auto b_span = b.AsSpan();
94   for (size_t i = 0; i < a_span.size(); i++) {
95     if (a_span[i] != b_span[i]) {
96       return false;
97     }
98   }
99   return true;
100 }
101 
102 constexpr bool operator!=(const Address& a, const Address& b) {
103   return !(a == b);
104 }
105 
106 }  // namespace pw::bluetooth
107