1/*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "bt_uuid.h"
17
18#include <sys/time.h>
19#include <algorithm>
20#include <cstdlib>
21#include "array"
22#include "securec.h"
23#include <cstdlib>
24#include "string"
25#include "sys/time.h"
26#include <ctime>
27
28namespace OHOS {
29namespace bluetooth {
30Uuid Uuid::Random()
31{
32    Uuid random;
33
34    struct timeval tv = {};
35    struct timezone tz = {};
36    struct tm randomTime = {};
37    unsigned int randNum = 0;
38    unsigned long int tvUsec = 0;
39
40    rand_r(&randNum);
41    gettimeofday(&tv, &tz);
42    localtime_r(&tv.tv_sec, &randomTime);
43
44    tvUsec = static_cast<unsigned long int>(tv.tv_usec);
45
46    random.uuid_[UUID_NODE_SIXTH_BYTE] =
47        static_cast<uint8_t>(tvUsec & 0x00000000000000FF);
48    random.uuid_[UUID_NODE_FIFTH_BYTE] =
49        static_cast<uint8_t>((tvUsec & 0x000000000000FF00) >> BASE_BIT_OPT_SIZE);
50    random.uuid_[UUID_NODE_FOURTH_BYTE] =
51        static_cast<uint8_t>((tvUsec & 0x0000000000FF0000) >> BIT_OPT_TWO_BYTE * BASE_BIT_OPT_SIZE);
52    random.uuid_[UUID_NODE_THIRD_BYTE] =
53        static_cast<uint8_t>((tvUsec & 0x00000000FF000000) >> BIT_OPT_THREE_BYTE * BASE_BIT_OPT_SIZE);
54    random.uuid_[UUID_NODE_FIRST_BYTE] =
55        static_cast<uint8_t>((tvUsec & 0x000000FF00000000) >> BIT_OPT_FOUR_BYTE * BASE_BIT_OPT_SIZE);
56    random.uuid_[UUID_CLOCK_SEQ] =
57        static_cast<uint8_t>((tvUsec & 0x0000FF0000000000) >> BIT_OPT_FIVE_BYTE * BASE_BIT_OPT_SIZE);
58    random.uuid_[UUID_VARIANT] =
59        static_cast<uint8_t>((tvUsec & 0x00FF000000000000) >> BIT_OPT_SIX_BYTE * BASE_BIT_OPT_SIZE);
60    random.uuid_[UUID_TIME_HIGH] =
61        static_cast<uint8_t>((tvUsec & 0xFF00000000000000) >> BIT_OPT_SEVEN_BYTE * BASE_BIT_OPT_SIZE);
62    random.uuid_[UUID_VERSION] =
63        static_cast<uint8_t>((static_cast<unsigned int>(randomTime.tm_sec) + randNum) & 0xFF);
64    random.uuid_[UUID_TIME_MID_SECEND_BYTE] =
65        static_cast<uint8_t>((static_cast<unsigned int>(randomTime.tm_min) + (randNum >> BASE_BIT_OPT_SIZE)) & 0xFF);
66    random.uuid_[UUID_TIME_MID_FIRST_BYTE] =
67        static_cast<uint8_t>((static_cast<unsigned int>(randomTime.tm_hour) +
68        (randNum >> BIT_OPT_TWO_BYTE * BASE_BIT_OPT_SIZE)) & 0xFF);
69    random.uuid_[UUID_TIME_LOW_FOURTH_BYTE] =
70        static_cast<uint8_t>((static_cast<unsigned int>(randomTime.tm_mday) +
71        (randNum >> BIT_OPT_THREE_BYTE * BASE_BIT_OPT_SIZE)) & 0xFF);
72    random.uuid_[UUID_TIME_LOW_THIRD_BYTE] =
73        static_cast<uint8_t>(static_cast<unsigned int>(randomTime.tm_mon) & 0xFF);
74    random.uuid_[UUID_TIME_LOW_SECEND_BYTE] =
75        static_cast<uint8_t>(static_cast<unsigned int>(randomTime.tm_year) & 0xFF);
76    random.uuid_[UUID_TIME_LOW_FIRST_BYTE] =
77        static_cast<uint8_t>((static_cast<unsigned int>(randomTime.tm_year) & 0xFF00) >> BASE_BIT_OPT_SIZE);
78
79    return random;
80}
81
82Uuid Uuid::ConvertFromString(const std::string &name)
83{
84    Uuid ret;
85    std::string tmp = name;
86    std::size_t pos = tmp.find("-");
87
88    while (pos != std::string::npos) {
89        tmp.replace(pos, 1, "");
90        pos = tmp.find("-");
91    }
92
93    for (std::size_t i = 0; (i + 1) < tmp.length(); i += SIZE_STRING_TO_INT) {
94        ret.uuid_[i / SIZE_STRING_TO_INT] = std::stoi(tmp.substr(i, SIZE_STRING_TO_INT), nullptr, UUID128_BYTES_TYPE);
95    }
96
97    return ret;
98}
99
100Uuid Uuid::ConvertFrom16Bits(uint16_t uuid)
101{
102    Uuid tmp;
103    tmp.uuid_[UUID_TIME_LOW_THIRD_BYTE] = static_cast<uint8_t>((uuid & 0xFF00) >> BASE_BIT_OPT_SIZE);
104    tmp.uuid_[UUID_TIME_LOW_FOURTH_BYTE] = static_cast<uint8_t>(uuid & 0x00FF);
105    return tmp;
106}
107
108Uuid Uuid::ConvertFrom32Bits(uint32_t uuid)
109{
110    Uuid tmp;
111    tmp.uuid_[UUID_TIME_LOW_FIRST_BYTE] =
112        static_cast<uint8_t>((uuid & 0xFF000000) >> BIT_OPT_THREE_BYTE * BASE_BIT_OPT_SIZE);
113    tmp.uuid_[UUID_TIME_LOW_SECEND_BYTE] =
114        static_cast<uint8_t>((uuid & 0x00FF0000) >> BIT_OPT_TWO_BYTE * BASE_BIT_OPT_SIZE);
115    tmp.uuid_[UUID_TIME_LOW_THIRD_BYTE] =
116        static_cast<uint8_t>((uuid & 0x0000FF00) >> BASE_BIT_OPT_SIZE);
117    tmp.uuid_[UUID_TIME_LOW_FOURTH_BYTE] =
118        static_cast<uint8_t>(uuid & 0x000000FF);
119    return tmp;
120}
121
122Uuid Uuid::ConvertFromBytesLE(const uint8_t *uuid, const size_t size)
123{
124    Uuid leUuid;
125    if (size < UUID128_BYTES_TYPE) {
126        return leUuid;
127    }
128    UUID128Bit le;
129    if (memcpy_s(le.data(), UUID128_BYTES_TYPE, uuid, UUID128_BYTES_TYPE) != EOK) {
130        return leUuid;
131    }
132    std::reverse_copy(le.data(), le.data() + UUID128_BYTES_TYPE, leUuid.uuid_.begin());
133    return leUuid;
134}
135
136Uuid Uuid::ConvertFromMostAndLeastBit(uint64_t mostSigBits, uint64_t leastSigBits)
137{
138    Uuid tmp;
139    int division = UUID128_BYTES_TYPE / SIZE_STRING_TO_INT;
140
141    for (int i = 0; i < division; i++) {
142        tmp.uuid_[i] = (mostSigBits >> (BASE_BIT_OPT_SIZE * (division - i - 1))) & 0xFF;
143    }
144
145    for (int i = division; i < UUID128_BYTES_TYPE; i++) {
146        tmp.uuid_[i] = (leastSigBits >> (BASE_BIT_OPT_SIZE * (2 * division - i - 1))) & 0xFF; // value of division * 2
147    }
148
149    return tmp;
150}
151
152Uuid Uuid::ConvertFrom128Bits(const UUID128Bit &uuid)
153{
154    Uuid tmp;
155    tmp.uuid_ = uuid;
156    return tmp;
157}
158
159uint16_t Uuid::ConvertTo16Bits() const
160{
161    uint16_t ret = uuid_[UUID_TIME_LOW_THIRD_BYTE] & 0xFF;
162    ret = (ret << BASE_BIT_OPT_SIZE) + uuid_[UUID_TIME_LOW_FOURTH_BYTE];
163    return ret;
164}
165
166uint32_t Uuid::ConvertTo32Bits() const
167{
168    uint32_t ret = 0;
169    for (int i = 0; i < UUID32_BYTES_TYPE; i++) {
170        ret = (ret << BASE_BIT_OPT_SIZE) + uuid_[i];
171    }
172    return ret;
173}
174
175bool Uuid::ConvertToBytesLE(uint8_t *value, const size_t size) const
176{
177    if (size < UUID128_BYTES_TYPE) {
178        return false;
179    }
180
181    UUID128Bit le;
182    std::reverse_copy(uuid_.data(), uuid_.data() + UUID128_BYTES_TYPE, le.begin());
183    if (memcpy_s(value, UUID128_BYTES_TYPE, le.data(), UUID128_BYTES_TYPE) != EOK) {
184        return false;
185    }
186    return true;
187}
188
189Uuid::UUID128Bit Uuid::ConvertTo128Bits() const
190{
191    return uuid_;
192}
193
194int Uuid::GetUuidType() const
195{
196    for (int i = UUID32_BYTES_TYPE; i < UUID128_BYTES_TYPE; i++) {
197        if (BASE_UUID[i] != uuid_[i]) {
198            return UUID128_BYTES_TYPE;
199        }
200    }
201
202    if ((uuid_[0] == 0) && (uuid_[1] == 0)) {
203        return UUID16_BYTES_TYPE;
204    }
205
206    return UUID32_BYTES_TYPE;
207}
208
209bool Uuid::operator==(const Uuid &rhs) const
210{
211    return (uuid_ == rhs.uuid_);
212}
213
214bool Uuid::operator!=(const Uuid &rhs) const
215{
216    return (uuid_ != rhs.uuid_);
217}
218}  // namespace bluetooth
219}  // namespace OHOS