blob: 2f56d66069ed622ecfbb1fc2caba6e5d305c66d3 [file] [log] [blame]
// Copyright 2022 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#pragma once
#include <array>
#include <cstdint>
#include "pw_assert/assert.h"
#include "pw_bluetooth/internal/hex.h"
#include "pw_span/span.h"
#include "pw_string/string.h"
namespace pw::bluetooth {
// A 48-bit bluetooth device address (BD_ADDR) in little endian format.
// See Core Spec v5.3 Volume 2, Part B, Section 1.2.
class Address {
public:
// String size of a hexadecimal representation of an Address, not including
// the null terminator.
static constexpr size_t kHexStringSize = 17;
// Create an Address from its binary representation.
// The first byte in the span is the last one in the hex representation, thus
// the BD_ADDR 00:11:22:33:44:55 should be created from the span with bytes:
// {0x55, 0x44, 0x33, 0x22, 0x11, 0x00}.
constexpr Address(const span<const uint8_t, 6> addr_span) : addr_() {
static_assert(addr_span.size() == sizeof(addr_));
for (size_t i = 0; i < sizeof(addr_); i++) {
addr_[i] = addr_span[i];
}
}
// Create an address from the hex format "00:11:22:33:44:55". The passed
// string must have a length of 17 and a ":" character on the 3rd, 6th, 9th,
// 12th and 15th positions. The hexadecimal representation is such that the
// first byte in the string is the last byte in the binary representation.
constexpr Address(const char (&str_addr)[kHexStringSize + 1]) : addr_() {
PW_ASSERT((str_addr[2] == ':') && (str_addr[5] == ':') &&
(str_addr[8] == ':') && (str_addr[11] == ':') &&
(str_addr[14] == ':'));
for (size_t i = 0; i < sizeof(addr_); i++) {
uint16_t value = (internal::HexToNibble(str_addr[3 * i]) << 4u) |
internal::HexToNibble(str_addr[3 * i + 1]);
addr_[sizeof(addr_) - 1 - i] = value;
PW_ASSERT(value <= 0xff);
}
}
// Return the bluetooth address a the 6-byte binary representation.
constexpr span<const uint8_t, 6> AsSpan() const {
return span<const uint8_t, 6>{addr_.data(), addr_.size()};
}
// Return an inline pw_string representation of the Address in hexadecimal
// using ":" characters as byte separator.
constexpr InlineString<kHexStringSize> ToString() const {
InlineString<kHexStringSize> ret;
for (size_t i = addr_.size(); i-- != 0;) {
ret += internal::NibbleToHex(addr_[i] >> 4);
ret += internal::NibbleToHex(addr_[i] & 0xf);
if (i) {
ret += ':';
}
}
return ret;
}
private:
std::array<uint8_t, 6> addr_;
};
// Address comparators:
constexpr bool operator==(const Address& a, const Address& b) {
const auto a_span = a.AsSpan();
const auto b_span = b.AsSpan();
for (size_t i = 0; i < a_span.size(); i++) {
if (a_span[i] != b_span[i]) {
return false;
}
}
return true;
}
constexpr bool operator!=(const Address& a, const Address& b) {
return !(a == b);
}
} // namespace pw::bluetooth