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/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
     41 UUID UUID::GetRandom() {
     42   UUID128Bit bytes;
     43   base::RandBytes(bytes.data(), bytes.size());
     44   return UUID(bytes);
     45 }
     46 
     47 // static
     48 UUID UUID::GetNil() {
     49   UUID128Bit bytes;
     50   bytes.fill(0);
     51   return UUID(bytes);
     52 }
     53 
     54 // static
     55 UUID UUID::GetMax() {
     56   UUID128Bit bytes;
     57   bytes.fill(1);
     58   return UUID(bytes);
     59 }
     60 
     61 void UUID::InitializeDefault() {
     62   // Initialize to Bluetooth SIG base UUID.
     63   id_ = kSigBaseUUID;
     64   is_valid_ = true;
     65 }
     66 
     67 UUID::UUID() {
     68   InitializeDefault();
     69 }
     70 
     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 
    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 
    121 UUID::UUID(const UUID16Bit& uuid) {
    122   InitializeDefault();
    123   std::copy(uuid.begin(), uuid.end(), id_.begin() + kNumBytes16);
    124 }
    125 
    126 UUID::UUID(const UUID32Bit& uuid) {
    127   InitializeDefault();
    128   std::copy(uuid.begin(), uuid.end(), id_.begin());
    129 }
    130 
    131 UUID::UUID(const UUID128Bit& uuid) : id_(uuid), is_valid_(true) {}
    132 
    133 UUID::UUID128Bit UUID::GetFullBigEndian() const {
    134   return id_;
    135 }
    136 
    137 UUID::UUID128Bit UUID::GetFullLittleEndian() const {
    138   UUID::UUID128Bit ret;
    139   std::reverse_copy(id_.begin(), id_.end(), ret.begin());
    140   return ret;
    141 }
    142 
    143 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 
    149 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 
    158 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 
    168 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 
    173 bool UUID::operator==(const UUID& rhs) const {
    174   return std::equal(id_.begin(), id_.end(), rhs.id_.begin());
    175 }
    176 
    177 }  // namespace bluetooth
    178