195489c19Sopenharmony_ci/*
295489c19Sopenharmony_ci * Copyright (C) 2021 Huawei Device Co., Ltd.
395489c19Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
495489c19Sopenharmony_ci * you may not use this file except in compliance with the License.
595489c19Sopenharmony_ci * You may obtain a copy of the License at
695489c19Sopenharmony_ci *
795489c19Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
895489c19Sopenharmony_ci *
995489c19Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1095489c19Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1195489c19Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1295489c19Sopenharmony_ci * See the License for the specific language governing permissions and
1395489c19Sopenharmony_ci * limitations under the License.
1495489c19Sopenharmony_ci */
1595489c19Sopenharmony_ci
1695489c19Sopenharmony_ci#include "bt_uuid.h"
1795489c19Sopenharmony_ci
1895489c19Sopenharmony_ci#include <sys/time.h>
1995489c19Sopenharmony_ci#include <algorithm>
2095489c19Sopenharmony_ci#include <cstdlib>
2195489c19Sopenharmony_ci#include "array"
2295489c19Sopenharmony_ci#include "securec.h"
2395489c19Sopenharmony_ci#include <cstdlib>
2495489c19Sopenharmony_ci#include "string"
2595489c19Sopenharmony_ci#include "sys/time.h"
2695489c19Sopenharmony_ci#include <ctime>
2795489c19Sopenharmony_ci
2895489c19Sopenharmony_cinamespace OHOS {
2995489c19Sopenharmony_cinamespace bluetooth {
3095489c19Sopenharmony_ciUuid Uuid::Random()
3195489c19Sopenharmony_ci{
3295489c19Sopenharmony_ci    Uuid random;
3395489c19Sopenharmony_ci
3495489c19Sopenharmony_ci    struct timeval tv = {};
3595489c19Sopenharmony_ci    struct timezone tz = {};
3695489c19Sopenharmony_ci    struct tm randomTime = {};
3795489c19Sopenharmony_ci    unsigned int randNum = 0;
3895489c19Sopenharmony_ci    unsigned long int tvUsec = 0;
3995489c19Sopenharmony_ci
4095489c19Sopenharmony_ci    rand_r(&randNum);
4195489c19Sopenharmony_ci    gettimeofday(&tv, &tz);
4295489c19Sopenharmony_ci    localtime_r(&tv.tv_sec, &randomTime);
4395489c19Sopenharmony_ci
4495489c19Sopenharmony_ci    tvUsec = static_cast<unsigned long int>(tv.tv_usec);
4595489c19Sopenharmony_ci
4695489c19Sopenharmony_ci    random.uuid_[UUID_NODE_SIXTH_BYTE] =
4795489c19Sopenharmony_ci        static_cast<uint8_t>(tvUsec & 0x00000000000000FF);
4895489c19Sopenharmony_ci    random.uuid_[UUID_NODE_FIFTH_BYTE] =
4995489c19Sopenharmony_ci        static_cast<uint8_t>((tvUsec & 0x000000000000FF00) >> BASE_BIT_OPT_SIZE);
5095489c19Sopenharmony_ci    random.uuid_[UUID_NODE_FOURTH_BYTE] =
5195489c19Sopenharmony_ci        static_cast<uint8_t>((tvUsec & 0x0000000000FF0000) >> BIT_OPT_TWO_BYTE * BASE_BIT_OPT_SIZE);
5295489c19Sopenharmony_ci    random.uuid_[UUID_NODE_THIRD_BYTE] =
5395489c19Sopenharmony_ci        static_cast<uint8_t>((tvUsec & 0x00000000FF000000) >> BIT_OPT_THREE_BYTE * BASE_BIT_OPT_SIZE);
5495489c19Sopenharmony_ci    random.uuid_[UUID_NODE_FIRST_BYTE] =
5595489c19Sopenharmony_ci        static_cast<uint8_t>((tvUsec & 0x000000FF00000000) >> BIT_OPT_FOUR_BYTE * BASE_BIT_OPT_SIZE);
5695489c19Sopenharmony_ci    random.uuid_[UUID_CLOCK_SEQ] =
5795489c19Sopenharmony_ci        static_cast<uint8_t>((tvUsec & 0x0000FF0000000000) >> BIT_OPT_FIVE_BYTE * BASE_BIT_OPT_SIZE);
5895489c19Sopenharmony_ci    random.uuid_[UUID_VARIANT] =
5995489c19Sopenharmony_ci        static_cast<uint8_t>((tvUsec & 0x00FF000000000000) >> BIT_OPT_SIX_BYTE * BASE_BIT_OPT_SIZE);
6095489c19Sopenharmony_ci    random.uuid_[UUID_TIME_HIGH] =
6195489c19Sopenharmony_ci        static_cast<uint8_t>((tvUsec & 0xFF00000000000000) >> BIT_OPT_SEVEN_BYTE * BASE_BIT_OPT_SIZE);
6295489c19Sopenharmony_ci    random.uuid_[UUID_VERSION] =
6395489c19Sopenharmony_ci        static_cast<uint8_t>((static_cast<unsigned int>(randomTime.tm_sec) + randNum) & 0xFF);
6495489c19Sopenharmony_ci    random.uuid_[UUID_TIME_MID_SECEND_BYTE] =
6595489c19Sopenharmony_ci        static_cast<uint8_t>((static_cast<unsigned int>(randomTime.tm_min) + (randNum >> BASE_BIT_OPT_SIZE)) & 0xFF);
6695489c19Sopenharmony_ci    random.uuid_[UUID_TIME_MID_FIRST_BYTE] =
6795489c19Sopenharmony_ci        static_cast<uint8_t>((static_cast<unsigned int>(randomTime.tm_hour) +
6895489c19Sopenharmony_ci        (randNum >> BIT_OPT_TWO_BYTE * BASE_BIT_OPT_SIZE)) & 0xFF);
6995489c19Sopenharmony_ci    random.uuid_[UUID_TIME_LOW_FOURTH_BYTE] =
7095489c19Sopenharmony_ci        static_cast<uint8_t>((static_cast<unsigned int>(randomTime.tm_mday) +
7195489c19Sopenharmony_ci        (randNum >> BIT_OPT_THREE_BYTE * BASE_BIT_OPT_SIZE)) & 0xFF);
7295489c19Sopenharmony_ci    random.uuid_[UUID_TIME_LOW_THIRD_BYTE] =
7395489c19Sopenharmony_ci        static_cast<uint8_t>(static_cast<unsigned int>(randomTime.tm_mon) & 0xFF);
7495489c19Sopenharmony_ci    random.uuid_[UUID_TIME_LOW_SECEND_BYTE] =
7595489c19Sopenharmony_ci        static_cast<uint8_t>(static_cast<unsigned int>(randomTime.tm_year) & 0xFF);
7695489c19Sopenharmony_ci    random.uuid_[UUID_TIME_LOW_FIRST_BYTE] =
7795489c19Sopenharmony_ci        static_cast<uint8_t>((static_cast<unsigned int>(randomTime.tm_year) & 0xFF00) >> BASE_BIT_OPT_SIZE);
7895489c19Sopenharmony_ci
7995489c19Sopenharmony_ci    return random;
8095489c19Sopenharmony_ci}
8195489c19Sopenharmony_ci
8295489c19Sopenharmony_ciUuid Uuid::ConvertFromString(const std::string &name)
8395489c19Sopenharmony_ci{
8495489c19Sopenharmony_ci    Uuid ret;
8595489c19Sopenharmony_ci    std::string tmp = name;
8695489c19Sopenharmony_ci    std::size_t pos = tmp.find("-");
8795489c19Sopenharmony_ci
8895489c19Sopenharmony_ci    while (pos != std::string::npos) {
8995489c19Sopenharmony_ci        tmp.replace(pos, 1, "");
9095489c19Sopenharmony_ci        pos = tmp.find("-");
9195489c19Sopenharmony_ci    }
9295489c19Sopenharmony_ci
9395489c19Sopenharmony_ci    for (std::size_t i = 0; (i + 1) < tmp.length(); i += SIZE_STRING_TO_INT) {
9495489c19Sopenharmony_ci        ret.uuid_[i / SIZE_STRING_TO_INT] = std::stoi(tmp.substr(i, SIZE_STRING_TO_INT), nullptr, UUID128_BYTES_TYPE);
9595489c19Sopenharmony_ci    }
9695489c19Sopenharmony_ci
9795489c19Sopenharmony_ci    return ret;
9895489c19Sopenharmony_ci}
9995489c19Sopenharmony_ci
10095489c19Sopenharmony_ciUuid Uuid::ConvertFrom16Bits(uint16_t uuid)
10195489c19Sopenharmony_ci{
10295489c19Sopenharmony_ci    Uuid tmp;
10395489c19Sopenharmony_ci    tmp.uuid_[UUID_TIME_LOW_THIRD_BYTE] = static_cast<uint8_t>((uuid & 0xFF00) >> BASE_BIT_OPT_SIZE);
10495489c19Sopenharmony_ci    tmp.uuid_[UUID_TIME_LOW_FOURTH_BYTE] = static_cast<uint8_t>(uuid & 0x00FF);
10595489c19Sopenharmony_ci    return tmp;
10695489c19Sopenharmony_ci}
10795489c19Sopenharmony_ci
10895489c19Sopenharmony_ciUuid Uuid::ConvertFrom32Bits(uint32_t uuid)
10995489c19Sopenharmony_ci{
11095489c19Sopenharmony_ci    Uuid tmp;
11195489c19Sopenharmony_ci    tmp.uuid_[UUID_TIME_LOW_FIRST_BYTE] =
11295489c19Sopenharmony_ci        static_cast<uint8_t>((uuid & 0xFF000000) >> BIT_OPT_THREE_BYTE * BASE_BIT_OPT_SIZE);
11395489c19Sopenharmony_ci    tmp.uuid_[UUID_TIME_LOW_SECEND_BYTE] =
11495489c19Sopenharmony_ci        static_cast<uint8_t>((uuid & 0x00FF0000) >> BIT_OPT_TWO_BYTE * BASE_BIT_OPT_SIZE);
11595489c19Sopenharmony_ci    tmp.uuid_[UUID_TIME_LOW_THIRD_BYTE] =
11695489c19Sopenharmony_ci        static_cast<uint8_t>((uuid & 0x0000FF00) >> BASE_BIT_OPT_SIZE);
11795489c19Sopenharmony_ci    tmp.uuid_[UUID_TIME_LOW_FOURTH_BYTE] =
11895489c19Sopenharmony_ci        static_cast<uint8_t>(uuid & 0x000000FF);
11995489c19Sopenharmony_ci    return tmp;
12095489c19Sopenharmony_ci}
12195489c19Sopenharmony_ci
12295489c19Sopenharmony_ciUuid Uuid::ConvertFromBytesLE(const uint8_t *uuid, const size_t size)
12395489c19Sopenharmony_ci{
12495489c19Sopenharmony_ci    Uuid leUuid;
12595489c19Sopenharmony_ci    if (size < UUID128_BYTES_TYPE) {
12695489c19Sopenharmony_ci        return leUuid;
12795489c19Sopenharmony_ci    }
12895489c19Sopenharmony_ci    UUID128Bit le;
12995489c19Sopenharmony_ci    if (memcpy_s(le.data(), UUID128_BYTES_TYPE, uuid, UUID128_BYTES_TYPE) != EOK) {
13095489c19Sopenharmony_ci        return leUuid;
13195489c19Sopenharmony_ci    }
13295489c19Sopenharmony_ci    std::reverse_copy(le.data(), le.data() + UUID128_BYTES_TYPE, leUuid.uuid_.begin());
13395489c19Sopenharmony_ci    return leUuid;
13495489c19Sopenharmony_ci}
13595489c19Sopenharmony_ci
13695489c19Sopenharmony_ciUuid Uuid::ConvertFromMostAndLeastBit(uint64_t mostSigBits, uint64_t leastSigBits)
13795489c19Sopenharmony_ci{
13895489c19Sopenharmony_ci    Uuid tmp;
13995489c19Sopenharmony_ci    int division = UUID128_BYTES_TYPE / SIZE_STRING_TO_INT;
14095489c19Sopenharmony_ci
14195489c19Sopenharmony_ci    for (int i = 0; i < division; i++) {
14295489c19Sopenharmony_ci        tmp.uuid_[i] = (mostSigBits >> (BASE_BIT_OPT_SIZE * (division - i - 1))) & 0xFF;
14395489c19Sopenharmony_ci    }
14495489c19Sopenharmony_ci
14595489c19Sopenharmony_ci    for (int i = division; i < UUID128_BYTES_TYPE; i++) {
14695489c19Sopenharmony_ci        tmp.uuid_[i] = (leastSigBits >> (BASE_BIT_OPT_SIZE * (2 * division - i - 1))) & 0xFF; // value of division * 2
14795489c19Sopenharmony_ci    }
14895489c19Sopenharmony_ci
14995489c19Sopenharmony_ci    return tmp;
15095489c19Sopenharmony_ci}
15195489c19Sopenharmony_ci
15295489c19Sopenharmony_ciUuid Uuid::ConvertFrom128Bits(const UUID128Bit &uuid)
15395489c19Sopenharmony_ci{
15495489c19Sopenharmony_ci    Uuid tmp;
15595489c19Sopenharmony_ci    tmp.uuid_ = uuid;
15695489c19Sopenharmony_ci    return tmp;
15795489c19Sopenharmony_ci}
15895489c19Sopenharmony_ci
15995489c19Sopenharmony_ciuint16_t Uuid::ConvertTo16Bits() const
16095489c19Sopenharmony_ci{
16195489c19Sopenharmony_ci    uint16_t ret = uuid_[UUID_TIME_LOW_THIRD_BYTE] & 0xFF;
16295489c19Sopenharmony_ci    ret = (ret << BASE_BIT_OPT_SIZE) + uuid_[UUID_TIME_LOW_FOURTH_BYTE];
16395489c19Sopenharmony_ci    return ret;
16495489c19Sopenharmony_ci}
16595489c19Sopenharmony_ci
16695489c19Sopenharmony_ciuint32_t Uuid::ConvertTo32Bits() const
16795489c19Sopenharmony_ci{
16895489c19Sopenharmony_ci    uint32_t ret = 0;
16995489c19Sopenharmony_ci    for (int i = 0; i < UUID32_BYTES_TYPE; i++) {
17095489c19Sopenharmony_ci        ret = (ret << BASE_BIT_OPT_SIZE) + uuid_[i];
17195489c19Sopenharmony_ci    }
17295489c19Sopenharmony_ci    return ret;
17395489c19Sopenharmony_ci}
17495489c19Sopenharmony_ci
17595489c19Sopenharmony_cibool Uuid::ConvertToBytesLE(uint8_t *value, const size_t size) const
17695489c19Sopenharmony_ci{
17795489c19Sopenharmony_ci    if (size < UUID128_BYTES_TYPE) {
17895489c19Sopenharmony_ci        return false;
17995489c19Sopenharmony_ci    }
18095489c19Sopenharmony_ci
18195489c19Sopenharmony_ci    UUID128Bit le;
18295489c19Sopenharmony_ci    std::reverse_copy(uuid_.data(), uuid_.data() + UUID128_BYTES_TYPE, le.begin());
18395489c19Sopenharmony_ci    if (memcpy_s(value, UUID128_BYTES_TYPE, le.data(), UUID128_BYTES_TYPE) != EOK) {
18495489c19Sopenharmony_ci        return false;
18595489c19Sopenharmony_ci    }
18695489c19Sopenharmony_ci    return true;
18795489c19Sopenharmony_ci}
18895489c19Sopenharmony_ci
18995489c19Sopenharmony_ciUuid::UUID128Bit Uuid::ConvertTo128Bits() const
19095489c19Sopenharmony_ci{
19195489c19Sopenharmony_ci    return uuid_;
19295489c19Sopenharmony_ci}
19395489c19Sopenharmony_ci
19495489c19Sopenharmony_ciint Uuid::GetUuidType() const
19595489c19Sopenharmony_ci{
19695489c19Sopenharmony_ci    for (int i = UUID32_BYTES_TYPE; i < UUID128_BYTES_TYPE; i++) {
19795489c19Sopenharmony_ci        if (BASE_UUID[i] != uuid_[i]) {
19895489c19Sopenharmony_ci            return UUID128_BYTES_TYPE;
19995489c19Sopenharmony_ci        }
20095489c19Sopenharmony_ci    }
20195489c19Sopenharmony_ci
20295489c19Sopenharmony_ci    if ((uuid_[0] == 0) && (uuid_[1] == 0)) {
20395489c19Sopenharmony_ci        return UUID16_BYTES_TYPE;
20495489c19Sopenharmony_ci    }
20595489c19Sopenharmony_ci
20695489c19Sopenharmony_ci    return UUID32_BYTES_TYPE;
20795489c19Sopenharmony_ci}
20895489c19Sopenharmony_ci
20995489c19Sopenharmony_cibool Uuid::operator==(const Uuid &rhs) const
21095489c19Sopenharmony_ci{
21195489c19Sopenharmony_ci    return (uuid_ == rhs.uuid_);
21295489c19Sopenharmony_ci}
21395489c19Sopenharmony_ci
21495489c19Sopenharmony_cibool Uuid::operator!=(const Uuid &rhs) const
21595489c19Sopenharmony_ci{
21695489c19Sopenharmony_ci    return (uuid_ != rhs.uuid_);
21795489c19Sopenharmony_ci}
21895489c19Sopenharmony_ci}  // namespace bluetooth
21995489c19Sopenharmony_ci}  // namespace OHOS