1 /****************************************************************************** 2 * 3 * Copyright (C) 2017 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19 #pragma once 20 21 #include <array> 22 #include <cstdint> 23 #include <optional> 24 #include <string> 25 26 #include "storage/serializable.h" 27 28 namespace bluetooth { 29 30 namespace hci { 31 32 // This class is representing Bluetooth UUIDs across whole stack. 33 // Here are some general endianness rules: 34 // 1. UUID is internally kept as as Big Endian. 35 // 2. Bytes representing UUID coming from upper layers, Java or Binder, are Big Endian. 36 // 3. Bytes representing UUID coming from lower layer, HCI packets, are Little Endian. 37 // 4. UUID in storage is always string. 38 class Uuid final : public storage::Serializable<Uuid> { 39 public: 40 static constexpr size_t kNumBytes128 = 16; 41 static constexpr size_t kNumBytes32 = 4; 42 static constexpr size_t kNumBytes16 = 2; 43 44 static constexpr size_t kString128BitLen = 36; 45 46 static const Uuid kEmpty; // 00000000-0000-0000-0000-000000000000 47 48 using UUID128Bit = std::array<uint8_t, kNumBytes128>; 49 50 Uuid() = default; 51 data()52 inline uint8_t* data() { return uu.data(); } 53 data()54 inline const uint8_t* data() const { return uu.data(); } 55 56 // storage::Serializable methods 57 // Converts string representing 128, 32, or 16 bit UUID in 58 // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, xxxxxxxx, or xxxx format to UUID. 59 // return uuid on success, std::nullopt otherwise 60 static std::optional<Uuid> FromString(const std::string& uuid); 61 static std::optional<Uuid> FromLegacyConfigString(const std::string& uuid); 62 // Returns string representing this UUID in 63 // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format, lowercase. 64 std::string ToString() const override; 65 std::string ToLegacyConfigString() const override; 66 67 // Returns the shortest possible representation of this UUID in bytes. Either 68 // kNumBytes16, kNumBytes32, or kNumBytes128 69 size_t GetShortestRepresentationSize() const; 70 71 // Returns true if this UUID can be represented as 16 bit. 72 bool Is16Bit() const; 73 74 // Returns 16 bit Little Endian representation of this UUID. Use 75 // GetShortestRepresentationSize() or Is16Bit() before using this method. 76 uint16_t As16Bit() const; 77 78 // Returns 32 bit Little Endian representation of this UUID. Use 79 // GetShortestRepresentationSize() before using this method. 80 uint32_t As32Bit() const; 81 82 // Converts 16bit Little Endian representation of UUID to UUID 83 static Uuid From16Bit(uint16_t uuid16bit); 84 85 // Converts 32bit Little Endian representation of UUID to UUID 86 static Uuid From32Bit(uint32_t uuid32bit); 87 88 // Converts 128 bit Big Endian array representing UUID to UUID. From128BitBE(const UUID128Bit & uuid)89 static Uuid From128BitBE(const UUID128Bit& uuid) { 90 Uuid u(uuid); 91 return u; 92 } 93 94 // Converts 128 bit Big Endian array representing UUID to UUID. |uuid| points 95 // to beginning of array. 96 static Uuid From128BitBE(const uint8_t* uuid); 97 98 // Converts 128 bit Little Endian array representing UUID to UUID. 99 static Uuid From128BitLE(const UUID128Bit& uuid); 100 101 // Converts 128 bit Little Endian array representing UUID to UUID. |uuid| 102 // points to beginning of array. 103 static Uuid From128BitLE(const uint8_t* uuid); 104 105 // Returns 128 bit Little Endian representation of this UUID 106 UUID128Bit To128BitLE() const; 107 108 // Returns 128 bit Big Endian representation of this UUID 109 const UUID128Bit& To128BitBE() const; 110 111 // Returns true if this UUID is equal to kEmpty 112 bool IsEmpty() const; 113 114 bool operator<(const Uuid& rhs) const; 115 bool operator==(const Uuid& rhs) const; 116 bool operator!=(const Uuid& rhs) const; 117 118 private: Uuid(const UUID128Bit & val)119 constexpr Uuid(const UUID128Bit& val) : uu{val} {} 120 121 // Network-byte-ordered ID (Big Endian). 122 UUID128Bit uu = {}; 123 }; 124 } // namespace hci 125 126 } // namespace bluetooth 127 128 inline std::ostream& operator<<(std::ostream& os, const bluetooth::hci::Uuid& a) { 129 os << a.ToString(); 130 return os; 131 } 132 133 // Custom std::hash specialization so that bluetooth::UUID can be used as a key 134 // in std::unordered_map. 135 namespace std { 136 137 template <> 138 struct hash<bluetooth::hci::Uuid> { 139 std::size_t operator()(const bluetooth::hci::Uuid& key) const { 140 const auto& uuid_bytes = key.To128BitBE(); 141 std::hash<std::string> hash_fn; 142 return hash_fn( 143 std::string(reinterpret_cast<const char*>(uuid_bytes.data()), uuid_bytes.size())); 144 } 145 }; 146 147 } // namespace std 148