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