|
| 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}. |
| 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. |
| 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. |
| 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. |
| 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 |
0 commit comments