| // Copyright 2017 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/common/device_address.h" |
| |
| #include "pw_string/format.h" |
| #include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/common/assert.h" |
| |
| #pragma clang diagnostic ignored "-Wswitch-enum" |
| |
| namespace bt { |
| namespace { |
| |
| std::string TypeToString(DeviceAddress::Type type) { |
| switch (type) { |
| case DeviceAddress::Type::kBREDR: |
| return "(BD_ADDR) "; |
| case DeviceAddress::Type::kLEPublic: |
| return "(LE publ) "; |
| case DeviceAddress::Type::kLERandom: |
| return "(LE rand) "; |
| case DeviceAddress::Type::kLEAnonymous: |
| return "(LE anon) "; |
| } |
| |
| return "(invalid) "; |
| } |
| |
| } // namespace |
| |
| DeviceAddressBytes::DeviceAddressBytes() { SetToZero(); } |
| |
| DeviceAddressBytes::DeviceAddressBytes( |
| std::array<uint8_t, kDeviceAddressSize> bytes) { |
| bytes_ = bytes; |
| } |
| |
| DeviceAddressBytes::DeviceAddressBytes(const ByteBuffer& bytes) { |
| BT_DEBUG_ASSERT(bytes.size() == bytes_.size()); |
| std::copy(bytes.cbegin(), bytes.cend(), bytes_.begin()); |
| } |
| |
| DeviceAddressBytes::DeviceAddressBytes(pw::bluetooth::emboss::BdAddrView view) { |
| pw::bluetooth::emboss::MakeBdAddrView(&bytes_).CopyFrom(view); |
| } |
| |
| std::string DeviceAddressBytes::ToString() const { |
| constexpr size_t out_size = sizeof("00:00:00:00:00:00"); |
| char out[out_size] = ""; |
| // Ignore errors. If an error occurs, an empty string will be returned. |
| pw::StatusWithSize result = |
| pw::string::Format({out, sizeof(out)}, |
| "%02X:%02X:%02X:%02X:%02X:%02X", |
| bytes_[5], |
| bytes_[4], |
| bytes_[3], |
| bytes_[2], |
| bytes_[1], |
| bytes_[0]); |
| BT_DEBUG_ASSERT(result.ok()); |
| return out; |
| } |
| |
| void DeviceAddressBytes::SetToZero() { bytes_.fill(0); } |
| |
| std::size_t DeviceAddressBytes::Hash() const { |
| uint64_t bytes_as_int = 0; |
| int shift_amount = 0; |
| for (const uint8_t& byte : bytes_) { |
| bytes_as_int |= (static_cast<uint64_t>(byte) << shift_amount); |
| shift_amount += 8; |
| } |
| |
| std::hash<uint64_t> hash_func; |
| return hash_func(bytes_as_int); |
| } |
| |
| DeviceAddress::DeviceAddress() : type_(Type::kBREDR) {} |
| |
| DeviceAddress::DeviceAddress(Type type, const DeviceAddressBytes& value) |
| : type_(type), value_(value) {} |
| |
| DeviceAddress::DeviceAddress(Type type, |
| std::array<uint8_t, kDeviceAddressSize> bytes) |
| : DeviceAddress(type, DeviceAddressBytes(bytes)) {} |
| |
| pw::bluetooth::emboss::LEAddressType DeviceAddress::DeviceAddrToLeAddr( |
| DeviceAddress::Type type) { |
| switch (type) { |
| case DeviceAddress::Type::kLEPublic: { |
| return pw::bluetooth::emboss::LEAddressType::PUBLIC; |
| } |
| case DeviceAddress::Type::kLERandom: { |
| return pw::bluetooth::emboss::LEAddressType::RANDOM; |
| } |
| default: { |
| BT_PANIC("invalid DeviceAddressType"); |
| } |
| } |
| } |
| |
| pw::bluetooth::emboss::LEPeerAddressType DeviceAddress::DeviceAddrToLePeerAddr( |
| Type type) { |
| switch (type) { |
| case DeviceAddress::Type::kBREDR: { |
| BT_PANIC("BR/EDR address not convertible to LE address"); |
| } |
| case DeviceAddress::Type::kLEPublic: { |
| return pw::bluetooth::emboss::LEPeerAddressType::PUBLIC; |
| } |
| case DeviceAddress::Type::kLERandom: { |
| return pw::bluetooth::emboss::LEPeerAddressType::RANDOM; |
| } |
| case DeviceAddress::Type::kLEAnonymous: { |
| return pw::bluetooth::emboss::LEPeerAddressType::ANONYMOUS; |
| } |
| default: { |
| BT_PANIC("invalid DeviceAddressType"); |
| } |
| } |
| } |
| |
| pw::bluetooth::emboss::LEPeerAddressTypeNoAnon |
| DeviceAddress::DeviceAddrToLePeerAddrNoAnon(Type type) { |
| switch (type) { |
| case DeviceAddress::Type::kBREDR: { |
| BT_PANIC("BR/EDR address not convertible to LE address"); |
| } |
| case DeviceAddress::Type::kLEPublic: { |
| return pw::bluetooth::emboss::LEPeerAddressTypeNoAnon::PUBLIC; |
| } |
| case DeviceAddress::Type::kLERandom: { |
| return pw::bluetooth::emboss::LEPeerAddressTypeNoAnon::RANDOM; |
| } |
| case DeviceAddress::Type::kLEAnonymous: { |
| BT_PANIC("invalid DeviceAddressType; anonymous type unsupported"); |
| } |
| default: { |
| BT_PANIC("invalid DeviceAddressType"); |
| } |
| } |
| } |
| |
| pw::bluetooth::emboss::LEOwnAddressType DeviceAddress::DeviceAddrToLEOwnAddr( |
| Type type) { |
| switch (type) { |
| case DeviceAddress::Type::kLERandom: { |
| return pw::bluetooth::emboss::LEOwnAddressType::RANDOM; |
| } |
| case DeviceAddress::Type::kLEPublic: { |
| return pw::bluetooth::emboss::LEOwnAddressType::PUBLIC; |
| } |
| case DeviceAddress::Type::kLEAnonymous: |
| case DeviceAddress::Type::kBREDR: |
| default: { |
| BT_PANIC("invalid DeviceAddressType"); |
| } |
| } |
| } |
| |
| DeviceAddress::Type DeviceAddress::LeAddrToDeviceAddr( |
| pw::bluetooth::emboss::LEAddressType type) { |
| switch (type) { |
| case pw::bluetooth::emboss::LEAddressType::PUBLIC: |
| case pw::bluetooth::emboss::LEAddressType::PUBLIC_IDENTITY: { |
| return DeviceAddress::Type::kLEPublic; |
| } |
| case pw::bluetooth::emboss::LEAddressType::RANDOM: |
| case pw::bluetooth::emboss::LEAddressType::RANDOM_IDENTITY: { |
| return DeviceAddress::Type::kLERandom; |
| } |
| default: { |
| BT_PANIC("invalid LEAddressType"); |
| } |
| } |
| } |
| |
| DeviceAddress::Type DeviceAddress::LeAddrToDeviceAddr( |
| pw::bluetooth::emboss::LEPeerAddressType type) { |
| switch (type) { |
| case pw::bluetooth::emboss::LEPeerAddressType::PUBLIC: { |
| return DeviceAddress::Type::kLEPublic; |
| } |
| case pw::bluetooth::emboss::LEPeerAddressType::RANDOM: { |
| return DeviceAddress::Type::kLERandom; |
| } |
| case pw::bluetooth::emboss::LEPeerAddressType::ANONYMOUS: { |
| return DeviceAddress::Type::kLEAnonymous; |
| } |
| default: { |
| BT_PANIC("invalid LEPeerAddressType"); |
| } |
| } |
| } |
| |
| DeviceAddress::Type DeviceAddress::LeAddrToDeviceAddr( |
| pw::bluetooth::emboss::LEPeerAddressTypeNoAnon type) { |
| switch (type) { |
| case pw::bluetooth::emboss::LEPeerAddressTypeNoAnon::PUBLIC: { |
| return DeviceAddress::Type::kLEPublic; |
| } |
| case pw::bluetooth::emboss::LEPeerAddressTypeNoAnon::RANDOM: { |
| return DeviceAddress::Type::kLERandom; |
| } |
| default: { |
| BT_PANIC("invalid LEPeerAddressTypeNoAnon"); |
| } |
| } |
| } |
| |
| std::optional<DeviceAddress::Type> DeviceAddress::LeAddrToDeviceAddr( |
| pw::bluetooth::emboss::LEExtendedAddressType type) { |
| switch (type) { |
| case pw::bluetooth::emboss::LEExtendedAddressType::PUBLIC: |
| case pw::bluetooth::emboss::LEExtendedAddressType::PUBLIC_IDENTITY: { |
| return DeviceAddress::Type::kLEPublic; |
| } |
| case pw::bluetooth::emboss::LEExtendedAddressType::RANDOM: |
| case pw::bluetooth::emboss::LEExtendedAddressType::RANDOM_IDENTITY: { |
| return DeviceAddress::Type::kLERandom; |
| } |
| case pw::bluetooth::emboss::LEExtendedAddressType::ANONYMOUS: { |
| return DeviceAddress::Type::kLEAnonymous; |
| } |
| default: { |
| return std::nullopt; |
| } |
| } |
| } |
| |
| bool DeviceAddress::IsResolvablePrivate() const { |
| // "The two most significant bits of [a RPA] shall be equal to 0 and 1". |
| // (Vol 6, Part B, 1.3.2.2). |
| uint8_t msb = value_.bytes()[5]; |
| return type_ == Type::kLERandom && (msb & 0b01000000) && (~msb & 0b10000000); |
| } |
| |
| bool DeviceAddress::IsNonResolvablePrivate() const { |
| // "The two most significant bits of [a NRPA] shall be equal to 0". |
| // (Vol 6, Part B, 1.3.2.2). |
| uint8_t msb = value_.bytes()[5]; |
| return type_ == Type::kLERandom && !(msb & 0b11000000); |
| } |
| |
| bool DeviceAddress::IsStaticRandom() const { |
| // "The two most significant bits of [a static random address] shall be equal |
| // to 1". (Vol 6, Part B, 1.3.2.1). |
| uint8_t msb = value_.bytes()[5]; |
| return type_ == Type::kLERandom && ((msb & 0b11000000) == 0b11000000); |
| } |
| |
| std::size_t DeviceAddress::Hash() const { |
| const Type type_for_hashing = IsPublic() ? Type::kBREDR : type_; |
| std::size_t const h1(std::hash<Type>{}(type_for_hashing)); |
| std::size_t h2 = value_.Hash(); |
| |
| return h1 ^ (h2 << 1); |
| } |
| |
| std::string DeviceAddress::ToString() const { |
| return TypeToString(type_) + value_.ToString(); |
| } |
| |
| } // namespace bt |
| |
| namespace std { |
| |
| hash<bt::DeviceAddress>::result_type hash<bt::DeviceAddress>::operator()( |
| argument_type const& value) const { |
| return value.Hash(); |
| } |
| |
| } // namespace std |