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() {
53     return uu.data();
54   }
55 
data()56   inline const uint8_t* data() const {
57     return uu.data();
58   }
59 
60   // storage::Serializable methods
61   // Converts string representing 128, 32, or 16 bit UUID in
62   // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, xxxxxxxx, or xxxx format to UUID.
63   // return uuid on success, std::nullopt otherwise
64   static std::optional<Uuid> FromString(const std::string& uuid);
65   static std::optional<Uuid> FromLegacyConfigString(const std::string& uuid);
66   // Returns string representing this UUID in
67   // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format, lowercase.
68   std::string ToString() const override;
69   std::string ToLegacyConfigString() const override;
70 
71   // Creates and returns a random 128-bit UUID.
72   static Uuid GetRandom();
73 
74   // Returns the shortest possible representation of this UUID in bytes. Either
75   // kNumBytes16, kNumBytes32, or kNumBytes128
76   size_t GetShortestRepresentationSize() const;
77 
78   // Returns true if this UUID can be represented as 16 bit.
79   bool Is16Bit() const;
80 
81   // Returns 16 bit Little Endian representation of this UUID. Use
82   // GetShortestRepresentationSize() or Is16Bit() before using this method.
83   uint16_t As16Bit() const;
84 
85   // Returns 32 bit Little Endian representation of this UUID. Use
86   // GetShortestRepresentationSize() before using this method.
87   uint32_t As32Bit() const;
88 
89   // Converts 16bit Little Endian representation of UUID to UUID
90   static Uuid From16Bit(uint16_t uuid16bit);
91 
92   // Converts 32bit Little Endian representation of UUID to UUID
93   static Uuid From32Bit(uint32_t uuid32bit);
94 
95   // Converts 128 bit Big Endian array representing UUID to UUID.
From128BitBE(const UUID128Bit & uuid)96   static Uuid From128BitBE(const UUID128Bit& uuid) {
97     Uuid u(uuid);
98     return u;
99   }
100 
101   // Converts 128 bit Big Endian array representing UUID to UUID. |uuid| points
102   // to beginning of array.
103   static Uuid From128BitBE(const uint8_t* uuid);
104 
105   // Converts 128 bit Little Endian array representing UUID to UUID.
106   static Uuid From128BitLE(const UUID128Bit& uuid);
107 
108   // Converts 128 bit Little Endian array representing UUID to UUID. |uuid|
109   // points to beginning of array.
110   static Uuid From128BitLE(const uint8_t* uuid);
111 
112   // Returns 128 bit Little Endian representation of this UUID
113   UUID128Bit To128BitLE() const;
114 
115   // Returns 128 bit Big Endian representation of this UUID
116   const UUID128Bit& To128BitBE() const;
117 
118   // Returns true if this UUID is equal to kEmpty
119   bool IsEmpty() const;
120 
121   bool operator<(const Uuid& rhs) const;
122   bool operator==(const Uuid& rhs) const;
123   bool operator!=(const Uuid& rhs) const;
124 
125  private:
Uuid(const UUID128Bit & val)126   constexpr Uuid(const UUID128Bit& val) : uu{val} {};
127 
128   // Network-byte-ordered ID (Big Endian).
129   UUID128Bit uu = {};
130 };
131 }  // namespace hci
132 
133 }  // namespace bluetooth
134 
135 inline std::ostream& operator<<(std::ostream& os, const bluetooth::hci::Uuid& a) {
136   os << a.ToString();
137   return os;
138 }
139 
140 // Custom std::hash specialization so that bluetooth::UUID can be used as a key
141 // in std::unordered_map.
142 namespace std {
143 
144 template <>
145 struct hash<bluetooth::hci::Uuid> {
146   std::size_t operator()(const bluetooth::hci::Uuid& key) const {
147     const auto& uuid_bytes = key.To128BitBE();
148     std::hash<std::string> hash_fn;
149     return hash_fn(std::string(reinterpret_cast<const char*>(uuid_bytes.data()), uuid_bytes.size()));
150   }
151 };
152 
153 }  // namespace std
154