1 /*
2 * Copyright (c) 2024 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 "bluetooth_ble_common.h"
17
18 #include "bluetooth_ble_ffi.h"
19 #include "bluetooth_log.h"
20
21 #include <regex>
22 #include <vector>
23
24 namespace OHOS {
25 namespace CJSystemapi {
26 namespace CJBluetoothBle {
27 using Bluetooth::BTConnectState;
28 using Bluetooth::GattCharacteristic;
29 using Bluetooth::GattDescriptor;
30 using Bluetooth::GattPermission;
31 using Bluetooth::GattService;
32 using namespace std;
33
34 namespace {
35 std::string g_deviceAddr;
36 } // namespace
37
MallocCString(const std::string & origin)38 char *MallocCString(const std::string &origin)
39 {
40 if (origin.empty()) {
41 return nullptr;
42 }
43 auto length = origin.length() + 1;
44 char *res = static_cast<char *>(malloc(sizeof(char) * length));
45 if (res == nullptr) {
46 return nullptr;
47 }
48 return std::char_traits<char>::copy(res, origin.c_str(), length);
49 }
50
Convert2CArrString(std::vector<std::string> & tids)51 CArrString Convert2CArrString(std::vector<std::string> &tids)
52 {
53 CArrString res{};
54 if (tids.empty()) {
55 return res;
56 }
57
58 size_t size = tids.size();
59 if (size == 0 || size > std::numeric_limits<size_t>::max() / sizeof(char *)) {
60 return res;
61 }
62 res.head = static_cast<char **>(malloc(sizeof(char *) * size));
63 if (res.head == nullptr) {
64 return res;
65 }
66
67 size_t i = 0;
68 for (; i < size; ++i) {
69 res.head[i] = MallocCString(tids[i]);
70 }
71 res.size = static_cast<int64_t>(i);
72
73 return res;
74 }
75
Convert2CArrUI8(std::vector<uint8_t> vec)76 CArrUI8 Convert2CArrUI8(std::vector<uint8_t> vec)
77 {
78 CArrUI8 res{};
79 if (vec.empty()) {
80 return res;
81 }
82 size_t size = vec.size();
83 if (size == 0 || size > std::numeric_limits<size_t>::max() / sizeof(uint8_t)) {
84 return res;
85 }
86 res.head = static_cast<uint8_t *>(malloc(sizeof(uint8_t) * vec.size()));
87 if (res.head == nullptr) {
88 return res;
89 }
90 size_t i = 0;
91 for (; i < vec.size(); i++) {
92 res.head[i] = vec[i];
93 }
94 res.size = static_cast<int64_t>(i);
95 return res;
96 }
97
ConvertBLEDescriptorToCJ(GattDescriptor & descriptor)98 NativeBLEDescriptor ConvertBLEDescriptorToCJ(GattDescriptor &descriptor)
99 {
100 NativeBLEDescriptor outDescriptor{};
101 outDescriptor.descriptorUuid = MallocCString(descriptor.GetUuid().ToString());
102 if (descriptor.GetCharacteristic() != nullptr) {
103 outDescriptor.characteristicUuid = MallocCString(descriptor.GetCharacteristic()->GetUuid().ToString());
104 if (descriptor.GetCharacteristic()->GetService() != nullptr) {
105 outDescriptor.serviceUuid =
106 MallocCString(descriptor.GetCharacteristic()->GetService()->GetUuid().ToString());
107 }
108 }
109
110 size_t valueSize;
111 uint8_t *valueData = descriptor.GetValue(&valueSize).get();
112 vector<uint8_t> vec(valueData, valueData + valueSize);
113 outDescriptor.descriptorValue = Convert2CArrUI8(vec);
114 return outDescriptor;
115 }
116
Convert2CArrBLEDescriptor(vector<GattDescriptor> & descriptors)117 CArrBLEDescriptor Convert2CArrBLEDescriptor(vector<GattDescriptor> &descriptors)
118 {
119 CArrBLEDescriptor res{};
120 if (descriptors.empty()) {
121 return res;
122 }
123 size_t size = descriptors.size();
124 if (size == 0 || size > (std::numeric_limits<size_t>::max() / sizeof(NativeBLEDescriptor))) {
125 return res;
126 }
127 res.head = static_cast<NativeBLEDescriptor *>(malloc(sizeof(NativeBLEDescriptor) * size));
128 if (res.head == nullptr) {
129 return res;
130 }
131 size_t i = 0;
132 for (; i < descriptors.size(); i++) {
133 res.head[i] = ConvertBLEDescriptorToCJ(descriptors[i]);
134 }
135 res.size = static_cast<int64_t>(i);
136 return res;
137 }
138
HasProperty(int properties,int propertyMask)139 bool HasProperty(int properties, int propertyMask)
140 {
141 if (properties < 0 || propertyMask < 0) {
142 HILOGE("properties or propertyMask is less than 0");
143 return false;
144 }
145 return (static_cast<unsigned int>(properties) & static_cast<unsigned int>(propertyMask)) != 0;
146 }
147
ConvertGattPropertiesToCJ(int properties)148 NativeGattProperties ConvertGattPropertiesToCJ(int properties)
149 {
150 NativeGattProperties outProperties{};
151 outProperties.write = HasProperty(properties, GattCharacteristic::WRITE);
152 outProperties.writeNoResponse = HasProperty(properties, GattCharacteristic::WRITE_WITHOUT_RESPONSE);
153 outProperties.read = HasProperty(properties, GattCharacteristic::READ);
154 outProperties.notify = HasProperty(properties, GattCharacteristic::NOTIFY);
155 outProperties.indicate = HasProperty(properties, GattCharacteristic::INDICATE);
156 return outProperties;
157 }
158
ConvertBLECharacteristicToCJ(GattCharacteristic & characteristic)159 NativeBLECharacteristic ConvertBLECharacteristicToCJ(GattCharacteristic &characteristic)
160 {
161 NativeBLECharacteristic outCharacteristic{};
162 outCharacteristic.characteristicUuid = MallocCString(characteristic.GetUuid().ToString());
163 if (characteristic.GetService() != nullptr) {
164 outCharacteristic.serviceUuid = MallocCString(characteristic.GetService()->GetUuid().ToString());
165 }
166
167 size_t valueSize = 0;
168 uint8_t *valueData = characteristic.GetValue(&valueSize).get();
169 vector<uint8_t> vec(valueData, valueData + valueSize);
170 outCharacteristic.characteristicValue = Convert2CArrUI8(vec);
171
172 outCharacteristic.descriptors = Convert2CArrBLEDescriptor(characteristic.GetDescriptors());
173
174 outCharacteristic.properties = ConvertGattPropertiesToCJ(characteristic.GetProperties());
175
176 return outCharacteristic;
177 }
178
Convert2CArrBLECharacteristic(std::vector<GattCharacteristic> characteristics)179 CArrBLECharacteristic Convert2CArrBLECharacteristic(std::vector<GattCharacteristic> characteristics)
180 {
181 CArrBLECharacteristic res{};
182 if (characteristics.empty()) {
183 return res;
184 }
185 size_t size = characteristics.size();
186 if (size == 0 || size > std::numeric_limits<size_t>::max() / sizeof(NativeBLECharacteristic)) {
187 return res;
188 }
189 res.head = static_cast<NativeBLECharacteristic *>(malloc(sizeof(NativeBLECharacteristic) * size));
190 if (res.head == nullptr) {
191 return res;
192 }
193 size_t i = 0;
194 for (; i < characteristics.size(); i++) {
195 res.head[i] = ConvertBLECharacteristicToCJ(characteristics[i]);
196 }
197 res.size = static_cast<int64_t>(i);
198 return res;
199 }
200
ConvertGattServiceToCJ(GattService service)201 NativeGattService ConvertGattServiceToCJ(GattService service)
202 {
203 NativeGattService outService{};
204 outService.serviceUuid = MallocCString(service.GetUuid().ToString());
205 outService.isPrimary = service.IsPrimary();
206 outService.characteristics = Convert2CArrBLECharacteristic(service.GetCharacteristics());
207 vector<GattService> services;
208 vector<std::reference_wrapper<GattService>> srvs = service.GetIncludedServices();
209 for (auto &srv : srvs) {
210 services.push_back(srv.get());
211 }
212 outService.includeServices = Convert2CArrGattService(services);
213 return outService;
214 }
215
Convert2CArrGattService(std::vector<GattService> services)216 CArrGattService Convert2CArrGattService(std::vector<GattService> services)
217 {
218 CArrGattService res{};
219 if (services.empty()) {
220 return res;
221 }
222 size_t size = services.size();
223 if (size == 0 || size > std::numeric_limits<size_t>::max() / sizeof(NativeGattService)) {
224 return res;
225 }
226 res.head = static_cast<NativeGattService *>(malloc(sizeof(NativeGattService) * services.size()));
227 if (res.head == nullptr) {
228 return res;
229 }
230 size_t i = 0;
231 for (; i < services.size(); i++) {
232 res.head[i] = ConvertGattServiceToCJ(services[i]);
233 }
234 res.size = static_cast<int64_t>(i);
235 return res;
236 }
237
GetGattClientDeviceId()238 std::string GetGattClientDeviceId()
239 {
240 return g_deviceAddr;
241 }
242
ConvertGattPermissions(const NativeGattPermission & nativePermissions)243 uint16_t ConvertGattPermissions(const NativeGattPermission &nativePermissions)
244 {
245 uint16_t permissions = 0;
246 if (nativePermissions.readable) {
247 permissions |= static_cast<uint16_t>(GattPermission::READABLE);
248 }
249 if (nativePermissions.writeable) {
250 permissions |= static_cast<uint16_t>(GattPermission::WRITEABLE);
251 }
252 if (nativePermissions.readEncrypted) {
253 permissions |= static_cast<uint16_t>(GattPermission::READ_ENCRYPTED_MITM);
254 }
255 if (nativePermissions.writeEncrypted) {
256 permissions |= static_cast<uint16_t>(GattPermission::WRITE_ENCRYPTED_MITM);
257 }
258 return permissions;
259 }
260
ConvertGattProperties(const NativeGattProperties & nativeProperties)261 uint16_t ConvertGattProperties(const NativeGattProperties &nativeProperties)
262 {
263 uint16_t properties = 0;
264 if (nativeProperties.read) {
265 properties |= static_cast<uint16_t>(GattCharacteristic::READ);
266 }
267 if (nativeProperties.write) {
268 properties |= static_cast<uint16_t>(GattCharacteristic::WRITE);
269 }
270 if (nativeProperties.writeNoResponse) {
271 properties |= static_cast<uint16_t>(GattCharacteristic::WRITE_WITHOUT_RESPONSE);
272 }
273 if (nativeProperties.notify) {
274 properties |= static_cast<uint16_t>(GattCharacteristic::NOTIFY);
275 }
276 if (nativeProperties.indicate) {
277 properties |= static_cast<uint16_t>(GattCharacteristic::INDICATE);
278 }
279 return properties;
280 }
281
GetProfileConnectionState(int state)282 int GetProfileConnectionState(int state)
283 {
284 int32_t profileConnectionState = ProfileConnectionState::STATE_DISCONNECTED;
285 switch (state) {
286 case static_cast<int32_t>(BTConnectState::CONNECTING):
287 HILOGD("STATE_CONNECTING(1)");
288 profileConnectionState = ProfileConnectionState::STATE_CONNECTING;
289 break;
290 case static_cast<int32_t>(BTConnectState::CONNECTED):
291 HILOGD("STATE_CONNECTED(2)");
292 profileConnectionState = ProfileConnectionState::STATE_CONNECTED;
293 break;
294 case static_cast<int32_t>(BTConnectState::DISCONNECTING):
295 HILOGD("STATE_DISCONNECTING(3)");
296 profileConnectionState = ProfileConnectionState::STATE_DISCONNECTING;
297 break;
298 case static_cast<int32_t>(BTConnectState::DISCONNECTED):
299 HILOGD("STATE_DISCONNECTED(0)");
300 profileConnectionState = ProfileConnectionState::STATE_DISCONNECTED;
301 break;
302 default:
303 break;
304 }
305 return profileConnectionState;
306 }
307
FreeNativeBLECharacteristic(NativeBLECharacteristic characteristic)308 void FreeNativeBLECharacteristic(NativeBLECharacteristic characteristic)
309 {
310 free(characteristic.characteristicUuid);
311 free(characteristic.serviceUuid);
312 for (int64_t i = 0; i < characteristic.descriptors.size; i++) {
313 NativeBLEDescriptor descriptor = characteristic.descriptors.head[i];
314 FreeNativeBLEDescriptor(descriptor);
315 }
316 free(characteristic.descriptors.head);
317 characteristic.characteristicUuid = nullptr;
318 characteristic.serviceUuid = nullptr;
319 characteristic.descriptors.head = nullptr;
320 }
321
FreeNativeBLEDescriptor(NativeBLEDescriptor descriptor)322 void FreeNativeBLEDescriptor(NativeBLEDescriptor descriptor)
323 {
324 free(descriptor.descriptorUuid);
325 free(descriptor.characteristicUuid);
326 free(descriptor.serviceUuid);
327 free(descriptor.descriptorValue.head);
328 descriptor.descriptorUuid = nullptr;
329 descriptor.characteristicUuid = nullptr;
330 descriptor.serviceUuid = nullptr;
331 descriptor.descriptorValue.head = nullptr;
332 }
333
334 } // namespace CJBluetoothBle
335 } // namespace CJSystemapi
336 } // namespace OHOS