blob: ca8a1425548621a7a6101774f1399df3dbb76a2b [file] [log] [blame]
/******************************************************************************
*
* Copyright (C) 2017 The Android Open Source Project
*
* 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:
*
* http://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 <optional>
#include <string>
#include "storage/serializable.h"
namespace bluetooth {
namespace hci {
// This class is representing Bluetooth UUIDs across whole stack.
// Here are some general endianness rules:
// 1. UUID is internally kept as as Big Endian.
// 2. Bytes representing UUID coming from upper layers, Java or Binder, are Big Endian.
// 3. Bytes representing UUID coming from lower layer, HCI packets, are Little Endian.
// 4. UUID in storage is always string.
class Uuid final : public storage::Serializable<Uuid> {
public:
static constexpr size_t kNumBytes128 = 16;
static constexpr size_t kNumBytes32 = 4;
static constexpr size_t kNumBytes16 = 2;
static constexpr size_t kString128BitLen = 36;
static const Uuid kEmpty; // 00000000-0000-0000-0000-000000000000
using UUID128Bit = std::array<uint8_t, kNumBytes128>;
Uuid() = default;
inline uint8_t* data() {
return uu.data();
}
inline const uint8_t* data() const {
return uu.data();
}
// storage::Serializable methods
// Converts string representing 128, 32, or 16 bit UUID in
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, xxxxxxxx, or xxxx format to UUID.
// return uuid on success, std::nullopt otherwise
static std::optional<Uuid> FromString(const std::string& uuid);
static std::optional<Uuid> FromLegacyConfigString(const std::string& uuid);
// Returns string representing this UUID in
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format, lowercase.
std::string ToString() const override;
std::string ToLegacyConfigString() const override;
// Creates and returns a random 128-bit UUID.
static Uuid GetRandom();
// Returns the shortest possible representation of this UUID in bytes. Either
// kNumBytes16, kNumBytes32, or kNumBytes128
size_t GetShortestRepresentationSize() const;
// Returns true if this UUID can be represented as 16 bit.
bool Is16Bit() const;
// Returns 16 bit Little Endian representation of this UUID. Use
// GetShortestRepresentationSize() or Is16Bit() before using this method.
uint16_t As16Bit() const;
// Returns 32 bit Little Endian representation of this UUID. Use
// GetShortestRepresentationSize() before using this method.
uint32_t As32Bit() const;
// Converts 16bit Little Endian representation of UUID to UUID
static Uuid From16Bit(uint16_t uuid16bit);
// Converts 32bit Little Endian representation of UUID to UUID
static Uuid From32Bit(uint32_t uuid32bit);
// Converts 128 bit Big Endian array representing UUID to UUID.
static Uuid From128BitBE(const UUID128Bit& uuid) {
Uuid u(uuid);
return u;
}
// Converts 128 bit Big Endian array representing UUID to UUID. |uuid| points
// to beginning of array.
static Uuid From128BitBE(const uint8_t* uuid);
// Converts 128 bit Little Endian array representing UUID to UUID.
static Uuid From128BitLE(const UUID128Bit& uuid);
// Converts 128 bit Little Endian array representing UUID to UUID. |uuid|
// points to beginning of array.
static Uuid From128BitLE(const uint8_t* uuid);
// Returns 128 bit Little Endian representation of this UUID
UUID128Bit To128BitLE() const;
// Returns 128 bit Big Endian representation of this UUID
const UUID128Bit& To128BitBE() const;
// Returns true if this UUID is equal to kEmpty
bool IsEmpty() const;
bool operator<(const Uuid& rhs) const;
bool operator==(const Uuid& rhs) const;
bool operator!=(const Uuid& rhs) const;
private:
constexpr Uuid(const UUID128Bit& val) : uu{val} {};
// Network-byte-ordered ID (Big Endian).
UUID128Bit uu = {};
};
} // namespace hci
} // namespace bluetooth
inline std::ostream& operator<<(std::ostream& os, const bluetooth::hci::Uuid& a) {
os << a.ToString();
return os;
}
// Custom std::hash specialization so that bluetooth::UUID can be used as a key
// in std::unordered_map.
namespace std {
template <>
struct hash<bluetooth::hci::Uuid> {
std::size_t operator()(const bluetooth::hci::Uuid& key) const {
const auto& uuid_bytes = key.To128BitBE();
std::hash<std::string> hash_fn;
return hash_fn(std::string(reinterpret_cast<const char*>(uuid_bytes.data()), uuid_bytes.size()));
}
};
} // namespace std