1 //
2 // Copyright (C) 2015 Google, Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at:
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include "service/common/bluetooth/uuid.h"
18
19 #include <algorithm>
20 #include <array>
21 #include <stack>
22 #include <string>
23
24 #include <base/rand_util.h>
25 #include <base/strings/stringprintf.h>
26 #include <base/strings/string_split.h>
27 #include <base/strings/string_util.h>
28
29 namespace bluetooth {
30
31 namespace {
32
33 const UUID::UUID128Bit kSigBaseUUID = {
34 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
35 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb }
36 };
37
38 } // namespace
39
40 // static
GetRandom()41 UUID UUID::GetRandom() {
42 UUID128Bit bytes;
43 base::RandBytes(bytes.data(), bytes.size());
44 return UUID(bytes);
45 }
46
47 // static
GetNil()48 UUID UUID::GetNil() {
49 UUID128Bit bytes;
50 bytes.fill(0);
51 return UUID(bytes);
52 }
53
54 // static
GetMax()55 UUID UUID::GetMax() {
56 UUID128Bit bytes;
57 bytes.fill(1);
58 return UUID(bytes);
59 }
60
InitializeDefault()61 void UUID::InitializeDefault() {
62 // Initialize to Bluetooth SIG base UUID.
63 id_ = kSigBaseUUID;
64 is_valid_ = true;
65 }
66
UUID()67 UUID::UUID() {
68 InitializeDefault();
69 }
70
UUID(std::string uuid)71 UUID::UUID(std::string uuid) {
72 InitializeDefault();
73 is_valid_ = false;
74
75 if (uuid.empty())
76 return;
77
78 if (uuid.size() < 11 && uuid.find("0x") == 0)
79 uuid = uuid.substr(2);
80
81 if (uuid.size() != 4 && uuid.size() != 8 && uuid.size() != 36)
82 return;
83
84 if (uuid.size() == 36) {
85 if (uuid[8] != '-')
86 return;
87 if (uuid[13] != '-')
88 return;
89 if (uuid[18] != '-')
90 return;
91 if (uuid[23] != '-')
92 return;
93
94 std::vector<std::string> tokens = base::SplitString(
95 uuid, "-", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
96
97 if (tokens.size() != 5)
98 return;
99
100 uuid = base::JoinString(tokens, "");
101 }
102
103 const int start_index = uuid.size() == 4 ? 2 : 0;
104 const size_t copy_size = std::min(id_.size(), uuid.size() / 2);
105 for (size_t i = 0; i < copy_size; ++i) {
106 std::string octet_text(uuid, i * 2, 2);
107 char* temp = nullptr;
108 id_[start_index + i] = strtol(octet_text.c_str(), &temp, 16);
109 if (*temp != '\0')
110 return;
111 }
112
113 is_valid_ = true;
114 }
115
UUID(const bt_uuid_t & uuid)116 UUID::UUID(const bt_uuid_t& uuid) {
117 std::reverse_copy(uuid.uu, uuid.uu + sizeof(uuid.uu), id_.begin());
118 is_valid_ = true;
119 }
120
UUID(const UUID16Bit & uuid)121 UUID::UUID(const UUID16Bit& uuid) {
122 InitializeDefault();
123 std::copy(uuid.begin(), uuid.end(), id_.begin() + kNumBytes16);
124 }
125
UUID(const UUID32Bit & uuid)126 UUID::UUID(const UUID32Bit& uuid) {
127 InitializeDefault();
128 std::copy(uuid.begin(), uuid.end(), id_.begin());
129 }
130
UUID(const UUID128Bit & uuid)131 UUID::UUID(const UUID128Bit& uuid) : id_(uuid), is_valid_(true) {}
132
GetFullBigEndian() const133 UUID::UUID128Bit UUID::GetFullBigEndian() const {
134 return id_;
135 }
136
GetFullLittleEndian() const137 UUID::UUID128Bit UUID::GetFullLittleEndian() const {
138 UUID::UUID128Bit ret;
139 std::reverse_copy(id_.begin(), id_.end(), ret.begin());
140 return ret;
141 }
142
GetBlueDroid() const143 bt_uuid_t UUID::GetBlueDroid() const {
144 bt_uuid_t ret;
145 std::reverse_copy(id_.begin(), id_.end(), ret.uu);
146 return ret;
147 }
148
ToString() const149 std::string UUID::ToString() const {
150 return base::StringPrintf(
151 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
152 id_[0], id_[1], id_[2], id_[3],
153 id_[4], id_[5], id_[6], id_[7],
154 id_[8], id_[9], id_[10], id_[11],
155 id_[12], id_[13], id_[14], id_[15]);
156 }
157
GetShortestRepresentationSize() const158 size_t UUID::GetShortestRepresentationSize() const {
159 if (memcmp(id_.data() + 4, kSigBaseUUID.data() + 4, id_.size() - 4) != 0)
160 return kNumBytes128;
161
162 if (id_[0] == 0 && id_[1] == 0)
163 return kNumBytes16;
164
165 return kNumBytes32;
166 }
167
operator <(const UUID & rhs) const168 bool UUID::operator<(const UUID& rhs) const {
169 return std::lexicographical_compare(id_.begin(), id_.end(), rhs.id_.begin(),
170 rhs.id_.end());
171 }
172
operator ==(const UUID & rhs) const173 bool UUID::operator==(const UUID& rhs) const {
174 return std::equal(id_.begin(), id_.end(), rhs.id_.begin());
175 }
176
177 } // namespace bluetooth
178