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 
28 namespace OHOS {
29 namespace bluetooth {
Random()30 Uuid 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 
ConvertFromString(const std::string & name)82 Uuid 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 
ConvertFrom16Bits(uint16_t uuid)100 Uuid 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 
ConvertFrom32Bits(uint32_t uuid)108 Uuid 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 
ConvertFromBytesLE(const uint8_t * uuid,const size_t size)122 Uuid 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 
ConvertFromMostAndLeastBit(uint64_t mostSigBits,uint64_t leastSigBits)136 Uuid 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 
ConvertFrom128Bits(const UUID128Bit & uuid)152 Uuid Uuid::ConvertFrom128Bits(const UUID128Bit &uuid)
153 {
154     Uuid tmp;
155     tmp.uuid_ = uuid;
156     return tmp;
157 }
158 
ConvertTo16Bits() const159 uint16_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 
ConvertTo32Bits() const166 uint32_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 
ConvertToBytesLE(uint8_t * value,const size_t size) const175 bool 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 
ConvertTo128Bits() const189 Uuid::UUID128Bit Uuid::ConvertTo128Bits() const
190 {
191     return uuid_;
192 }
193 
GetUuidType() const194 int 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 
operator ==(const Uuid & rhs) const209 bool Uuid::operator==(const Uuid &rhs) const
210 {
211     return (uuid_ == rhs.uuid_);
212 }
213 
operator !=(const Uuid & rhs) const214 bool Uuid::operator!=(const Uuid &rhs) const
215 {
216     return (uuid_ != rhs.uuid_);
217 }
218 }  // namespace bluetooth
219 }  // namespace OHOS