• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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