summaryrefslogtreecommitdiff
path: root/system/gd/hci/uuid.h
blob: ca8a1425548621a7a6101774f1399df3dbb76a2b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/******************************************************************************
 *
 *  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