Home | History | Annotate | Download | only in bluetooth
      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/string_split.h>
     26 #include <base/strings/string_util.h>
     27 #include <base/strings/stringprintf.h>
     28 
     29 namespace bluetooth {
     30 
     31 namespace {
     32 
     33 const UUID::UUID128Bit kSigBaseUUID = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     34                                         0x10, 0x00, 0x80, 0x00, 0x00, 0x80,
     35                                         0x5f, 0x9b, 0x34, 0xfb}};
     36 
     37 }  // namespace
     38 
     39 // static
     40 UUID UUID::GetRandom() {
     41   UUID128Bit bytes;
     42   base::RandBytes(bytes.data(), bytes.size());
     43   return UUID(bytes);
     44 }
     45 
     46 // static
     47 UUID UUID::GetNil() {
     48   UUID128Bit bytes;
     49   bytes.fill(0);
     50   return UUID(bytes);
     51 }
     52 
     53 // static
     54 UUID UUID::GetMax() {
     55   UUID128Bit bytes;
     56   bytes.fill(1);
     57   return UUID(bytes);
     58 }
     59 
     60 void UUID::InitializeDefault() {
     61   // Initialize to Bluetooth SIG base UUID.
     62   id_ = kSigBaseUUID;
     63   is_valid_ = true;
     64 }
     65 
     66 UUID::UUID() { InitializeDefault(); }
     67 
     68 UUID::UUID(std::string uuid) {
     69   InitializeDefault();
     70   is_valid_ = false;
     71 
     72   if (uuid.empty()) return;
     73 
     74   if (uuid.size() < 11 && uuid.find("0x") == 0) uuid = uuid.substr(2);
     75 
     76   if (uuid.size() != 4 && uuid.size() != 8 && uuid.size() != 36) return;
     77 
     78   if (uuid.size() == 36) {
     79     if (uuid[8] != '-') return;
     80     if (uuid[13] != '-') return;
     81     if (uuid[18] != '-') return;
     82     if (uuid[23] != '-') return;
     83 
     84     std::vector<std::string> tokens = base::SplitString(
     85         uuid, "-", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
     86 
     87     if (tokens.size() != 5) return;
     88 
     89     uuid = base::JoinString(tokens, "");
     90   }
     91 
     92   const int start_index = uuid.size() == 4 ? 2 : 0;
     93   const size_t copy_size = std::min(id_.size(), uuid.size() / 2);
     94   for (size_t i = 0; i < copy_size; ++i) {
     95     std::string octet_text(uuid, i * 2, 2);
     96     char* temp = nullptr;
     97     id_[start_index + i] = strtol(octet_text.c_str(), &temp, 16);
     98     if (*temp != '\0') return;
     99   }
    100 
    101   is_valid_ = true;
    102 }
    103 
    104 UUID::UUID(const bt_uuid_t& uuid) {
    105   std::reverse_copy(uuid.uu, uuid.uu + sizeof(uuid.uu), id_.begin());
    106   is_valid_ = true;
    107 }
    108 
    109 UUID::UUID(const UUID16Bit& uuid) {
    110   InitializeDefault();
    111   std::copy(uuid.begin(), uuid.end(), id_.begin() + kNumBytes16);
    112 }
    113 
    114 UUID::UUID(const UUID32Bit& uuid) {
    115   InitializeDefault();
    116   std::copy(uuid.begin(), uuid.end(), id_.begin());
    117 }
    118 
    119 UUID::UUID(const UUID128Bit& uuid) : id_(uuid), is_valid_(true) {}
    120 
    121 UUID::UUID128Bit UUID::GetFullBigEndian() const { return id_; }
    122 
    123 UUID::UUID128Bit UUID::GetFullLittleEndian() const {
    124   UUID::UUID128Bit ret;
    125   std::reverse_copy(id_.begin(), id_.end(), ret.begin());
    126   return ret;
    127 }
    128 
    129 bt_uuid_t UUID::GetBlueDroid() const {
    130   bt_uuid_t ret;
    131   std::reverse_copy(id_.begin(), id_.end(), ret.uu);
    132   return ret;
    133 }
    134 
    135 std::string UUID::ToString() const {
    136   return base::StringPrintf(
    137       "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
    138       id_[0], id_[1], id_[2], id_[3], id_[4], id_[5], id_[6], id_[7], id_[8],
    139       id_[9], id_[10], id_[11], id_[12], id_[13], id_[14], id_[15]);
    140 }
    141 
    142 size_t UUID::GetShortestRepresentationSize() const {
    143   if (memcmp(id_.data() + 4, kSigBaseUUID.data() + 4, id_.size() - 4) != 0)
    144     return kNumBytes128;
    145 
    146   if (id_[0] == 0 && id_[1] == 0) return kNumBytes16;
    147 
    148   return kNumBytes32;
    149 }
    150 
    151 bool UUID::operator<(const UUID& rhs) const {
    152   return std::lexicographical_compare(id_.begin(), id_.end(), rhs.id_.begin(),
    153                                       rhs.id_.end());
    154 }
    155 
    156 bool UUID::operator==(const UUID& rhs) const {
    157   return std::equal(id_.begin(), id_.end(), rhs.id_.begin());
    158 }
    159 
    160 }  // namespace bluetooth
    161