1*635a8641SAndroid Build Coastguard Worker // Copyright 2014 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard Worker #include "device/bluetooth/bluetooth_uuid.h"
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard Worker #include <stddef.h>
8*635a8641SAndroid Build Coastguard Worker
9*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
10*635a8641SAndroid Build Coastguard Worker #include "base/strings/string_piece.h"
11*635a8641SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
13*635a8641SAndroid Build Coastguard Worker
14*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN)
15*635a8641SAndroid Build Coastguard Worker #include <objbase.h>
16*635a8641SAndroid Build Coastguard Worker
17*635a8641SAndroid Build Coastguard Worker #include "base/strings/string16.h"
18*635a8641SAndroid Build Coastguard Worker #endif // defined(OS_WIN)
19*635a8641SAndroid Build Coastguard Worker
20*635a8641SAndroid Build Coastguard Worker namespace device {
21*635a8641SAndroid Build Coastguard Worker
22*635a8641SAndroid Build Coastguard Worker namespace {
23*635a8641SAndroid Build Coastguard Worker
24*635a8641SAndroid Build Coastguard Worker const char kCommonUuidPostfix[] = "-0000-1000-8000-00805f9b34fb";
25*635a8641SAndroid Build Coastguard Worker const char kCommonUuidPrefix[] = "0000";
26*635a8641SAndroid Build Coastguard Worker
27*635a8641SAndroid Build Coastguard Worker // Returns the canonical, 128-bit canonical, and the format of the UUID
28*635a8641SAndroid Build Coastguard Worker // in |canonical|, |canonical_128|, and |format| based on |uuid|.
GetCanonicalUuid(std::string uuid,std::string * canonical,std::string * canonical_128,BluetoothUUID::Format * format)29*635a8641SAndroid Build Coastguard Worker void GetCanonicalUuid(std::string uuid,
30*635a8641SAndroid Build Coastguard Worker std::string* canonical,
31*635a8641SAndroid Build Coastguard Worker std::string* canonical_128,
32*635a8641SAndroid Build Coastguard Worker BluetoothUUID::Format* format) {
33*635a8641SAndroid Build Coastguard Worker // Initialize the values for the failure case.
34*635a8641SAndroid Build Coastguard Worker canonical->clear();
35*635a8641SAndroid Build Coastguard Worker canonical_128->clear();
36*635a8641SAndroid Build Coastguard Worker *format = BluetoothUUID::kFormatInvalid;
37*635a8641SAndroid Build Coastguard Worker
38*635a8641SAndroid Build Coastguard Worker if (uuid.empty())
39*635a8641SAndroid Build Coastguard Worker return;
40*635a8641SAndroid Build Coastguard Worker
41*635a8641SAndroid Build Coastguard Worker if (uuid.size() < 11 &&
42*635a8641SAndroid Build Coastguard Worker base::StartsWith(uuid, "0x", base::CompareCase::SENSITIVE)) {
43*635a8641SAndroid Build Coastguard Worker uuid = uuid.substr(2);
44*635a8641SAndroid Build Coastguard Worker }
45*635a8641SAndroid Build Coastguard Worker
46*635a8641SAndroid Build Coastguard Worker if (!(uuid.size() == 4 || uuid.size() == 8 || uuid.size() == 36))
47*635a8641SAndroid Build Coastguard Worker return;
48*635a8641SAndroid Build Coastguard Worker
49*635a8641SAndroid Build Coastguard Worker for (size_t i = 0; i < uuid.size(); ++i) {
50*635a8641SAndroid Build Coastguard Worker if (i == 8 || i == 13 || i == 18 || i == 23) {
51*635a8641SAndroid Build Coastguard Worker if (uuid[i] != '-')
52*635a8641SAndroid Build Coastguard Worker return;
53*635a8641SAndroid Build Coastguard Worker } else {
54*635a8641SAndroid Build Coastguard Worker if (!base::IsHexDigit(uuid[i]))
55*635a8641SAndroid Build Coastguard Worker return;
56*635a8641SAndroid Build Coastguard Worker uuid[i] = base::ToLowerASCII(uuid[i]);
57*635a8641SAndroid Build Coastguard Worker }
58*635a8641SAndroid Build Coastguard Worker }
59*635a8641SAndroid Build Coastguard Worker
60*635a8641SAndroid Build Coastguard Worker canonical->assign(uuid);
61*635a8641SAndroid Build Coastguard Worker if (uuid.size() == 4) {
62*635a8641SAndroid Build Coastguard Worker canonical_128->assign(kCommonUuidPrefix + uuid + kCommonUuidPostfix);
63*635a8641SAndroid Build Coastguard Worker *format = BluetoothUUID::kFormat16Bit;
64*635a8641SAndroid Build Coastguard Worker } else if (uuid.size() == 8) {
65*635a8641SAndroid Build Coastguard Worker canonical_128->assign(uuid + kCommonUuidPostfix);
66*635a8641SAndroid Build Coastguard Worker *format = BluetoothUUID::kFormat32Bit;
67*635a8641SAndroid Build Coastguard Worker } else {
68*635a8641SAndroid Build Coastguard Worker canonical_128->assign(uuid);
69*635a8641SAndroid Build Coastguard Worker *format = BluetoothUUID::kFormat128Bit;
70*635a8641SAndroid Build Coastguard Worker }
71*635a8641SAndroid Build Coastguard Worker }
72*635a8641SAndroid Build Coastguard Worker
73*635a8641SAndroid Build Coastguard Worker } // namespace
74*635a8641SAndroid Build Coastguard Worker
75*635a8641SAndroid Build Coastguard Worker
BluetoothUUID(const std::string & uuid)76*635a8641SAndroid Build Coastguard Worker BluetoothUUID::BluetoothUUID(const std::string& uuid) {
77*635a8641SAndroid Build Coastguard Worker GetCanonicalUuid(uuid, &value_, &canonical_value_, &format_);
78*635a8641SAndroid Build Coastguard Worker }
79*635a8641SAndroid Build Coastguard Worker
80*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN)
BluetoothUUID(GUID uuid)81*635a8641SAndroid Build Coastguard Worker BluetoothUUID::BluetoothUUID(GUID uuid) {
82*635a8641SAndroid Build Coastguard Worker // 36 chars for UUID + 2 chars for braces + 1 char for null-terminator.
83*635a8641SAndroid Build Coastguard Worker constexpr int kBufferSize = 39;
84*635a8641SAndroid Build Coastguard Worker wchar_t buffer[kBufferSize];
85*635a8641SAndroid Build Coastguard Worker int result = ::StringFromGUID2(uuid, buffer, kBufferSize);
86*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(kBufferSize, result);
87*635a8641SAndroid Build Coastguard Worker DCHECK_EQ('{', buffer[0]);
88*635a8641SAndroid Build Coastguard Worker DCHECK_EQ('}', buffer[37]);
89*635a8641SAndroid Build Coastguard Worker
90*635a8641SAndroid Build Coastguard Worker GetCanonicalUuid(base::WideToUTF8(base::WStringPiece(buffer).substr(1, 36)),
91*635a8641SAndroid Build Coastguard Worker &value_, &canonical_value_, &format_);
92*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(kFormat128Bit, format_);
93*635a8641SAndroid Build Coastguard Worker }
94*635a8641SAndroid Build Coastguard Worker #endif // defined(OS_WIN)
95*635a8641SAndroid Build Coastguard Worker
BluetoothUUID()96*635a8641SAndroid Build Coastguard Worker BluetoothUUID::BluetoothUUID() : format_(kFormatInvalid) {
97*635a8641SAndroid Build Coastguard Worker }
98*635a8641SAndroid Build Coastguard Worker
99*635a8641SAndroid Build Coastguard Worker BluetoothUUID::~BluetoothUUID() = default;
100*635a8641SAndroid Build Coastguard Worker
101*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN)
102*635a8641SAndroid Build Coastguard Worker // static
GetCanonicalValueAsGUID(base::StringPiece uuid)103*635a8641SAndroid Build Coastguard Worker GUID BluetoothUUID::GetCanonicalValueAsGUID(base::StringPiece uuid) {
104*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(36u, uuid.size());
105*635a8641SAndroid Build Coastguard Worker base::string16 braced_uuid = L'{' + base::UTF8ToWide(uuid) + L'}';
106*635a8641SAndroid Build Coastguard Worker GUID guid;
107*635a8641SAndroid Build Coastguard Worker CHECK_EQ(NOERROR, ::CLSIDFromString(braced_uuid.data(), &guid));
108*635a8641SAndroid Build Coastguard Worker return guid;
109*635a8641SAndroid Build Coastguard Worker }
110*635a8641SAndroid Build Coastguard Worker #endif // defined(OS_WIN)
111*635a8641SAndroid Build Coastguard Worker
IsValid() const112*635a8641SAndroid Build Coastguard Worker bool BluetoothUUID::IsValid() const {
113*635a8641SAndroid Build Coastguard Worker return format_ != kFormatInvalid;
114*635a8641SAndroid Build Coastguard Worker }
115*635a8641SAndroid Build Coastguard Worker
operator <(const BluetoothUUID & uuid) const116*635a8641SAndroid Build Coastguard Worker bool BluetoothUUID::operator<(const BluetoothUUID& uuid) const {
117*635a8641SAndroid Build Coastguard Worker return canonical_value_ < uuid.canonical_value_;
118*635a8641SAndroid Build Coastguard Worker }
119*635a8641SAndroid Build Coastguard Worker
operator ==(const BluetoothUUID & uuid) const120*635a8641SAndroid Build Coastguard Worker bool BluetoothUUID::operator==(const BluetoothUUID& uuid) const {
121*635a8641SAndroid Build Coastguard Worker return canonical_value_ == uuid.canonical_value_;
122*635a8641SAndroid Build Coastguard Worker }
123*635a8641SAndroid Build Coastguard Worker
operator !=(const BluetoothUUID & uuid) const124*635a8641SAndroid Build Coastguard Worker bool BluetoothUUID::operator!=(const BluetoothUUID& uuid) const {
125*635a8641SAndroid Build Coastguard Worker return canonical_value_ != uuid.canonical_value_;
126*635a8641SAndroid Build Coastguard Worker }
127*635a8641SAndroid Build Coastguard Worker
PrintTo(const BluetoothUUID & uuid,std::ostream * out)128*635a8641SAndroid Build Coastguard Worker void PrintTo(const BluetoothUUID& uuid, std::ostream* out) {
129*635a8641SAndroid Build Coastguard Worker *out << uuid.canonical_value();
130*635a8641SAndroid Build Coastguard Worker }
131*635a8641SAndroid Build Coastguard Worker
132*635a8641SAndroid Build Coastguard Worker } // namespace device
133