• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   // String size of a hexadecimal representation of an Address, not including
31   // the null terminator.
32   static constexpr size_t kHexStringSize = 17;
33 
34   // Create an Address from its binary representation.
35   // The first byte in the span is the last one in the hex representation, thus
36   // the BD_ADDR 00:11:22:33:44:55 should be created from the span with bytes:
37   // {0x55, 0x44, 0x33, 0x22, 0x11, 0x00}.
Address(const span<const uint8_t,6> addr_span)38   constexpr Address(const span<const uint8_t, 6> addr_span) : addr_() {
39     static_assert(addr_span.size() == sizeof(addr_));
40     for (size_t i = 0; i < sizeof(addr_); i++) {
41       addr_[i] = addr_span[i];
42     }
43   }
44 
45   // Create an address from the hex format "00:11:22:33:44:55". The passed
46   // string must have a length of 17 and a ":" character on the 3rd, 6th, 9th,
47   // 12th and 15th positions. The hexadecimal representation is such that the
48   // first byte in the string is the last byte in the binary representation.
Address(const char (& str_addr)[kHexStringSize+1])49   constexpr Address(const char (&str_addr)[kHexStringSize + 1]) : addr_() {
50     PW_ASSERT((str_addr[2] == ':') && (str_addr[5] == ':') &&
51               (str_addr[8] == ':') && (str_addr[11] == ':') &&
52               (str_addr[14] == ':'));
53     for (size_t i = 0; i < sizeof(addr_); i++) {
54       uint16_t value = (internal::HexToNibble(str_addr[3 * i]) << 4u) |
55                        internal::HexToNibble(str_addr[3 * i + 1]);
56       addr_[sizeof(addr_) - 1 - i] = value;
57       PW_ASSERT(value <= 0xff);
58     }
59   }
60 
61   // Return the bluetooth address a the 6-byte binary representation.
AsSpan()62   constexpr span<const uint8_t, 6> AsSpan() const {
63     return span<const uint8_t, 6>{addr_.data(), addr_.size()};
64   }
65 
66   // Return an inline pw_string representation of the Address in hexadecimal
67   // using ":" characters as byte separator.
ToString()68   constexpr InlineString<kHexStringSize> ToString() const {
69     InlineString<kHexStringSize> ret;
70     for (size_t i = addr_.size(); i-- != 0;) {
71       ret += internal::NibbleToHex(addr_[i] >> 4);
72       ret += internal::NibbleToHex(addr_[i] & 0xf);
73       if (i) {
74         ret += ':';
75       }
76     }
77     return ret;
78   }
79 
80  private:
81   std::array<uint8_t, 6> addr_;
82 };
83 
84 // Address comparators:
85 constexpr bool operator==(const Address& a, const Address& b) {
86   const auto a_span = a.AsSpan();
87   const auto b_span = b.AsSpan();
88   for (size_t i = 0; i < a_span.size(); i++) {
89     if (a_span[i] != b_span[i]) {
90       return false;
91     }
92   }
93   return true;
94 }
95 
96 constexpr bool operator!=(const Address& a, const Address& b) {
97   return !(a == b);
98 }
99 
100 }  // namespace pw::bluetooth
101