1 /*
2 * Copyright (C) 2021-2022 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 "ohos_bt_gatt_client.h"
17 #include <cstring>
18 #include <map>
19 #include "__config"
20 #include <functional>
21
22 #include "bluetooth_gatt_characteristic.h"
23 #include "bluetooth_gatt_client.h"
24 #include "bluetooth_gatt_descriptor.h"
25 #include "bluetooth_gatt_service.h"
26 #include "bluetooth_log.h"
27 #include "bluetooth_utils.h"
28 #include "bluetooth_remote_device.h"
29
30 #include "iosfwd"
31 #include "memory"
32 #include "new"
33 #include "ohos_bt_adapter_utils.h"
34 #include "ohos_bt_def.h"
35 #include "optional"
36 #include "string"
37 #include "type_traits"
38 #include "utility"
39 #include "uuid.h"
40
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44
45 using namespace std;
46
47 namespace OHOS {
48 namespace Bluetooth {
49 class GattClientCallbackWrapper;
50
51 struct GattClientWrapper {
52 std::shared_ptr<GattClient> gattClient;
53 GattClientCallbackWrapper *gattClientCallback;
54 string remoteAddr;
55 bool fastestConnFlag;
56 };
57
58 using ClientIterator = std::map<int, struct GattClientWrapper>::iterator;
59
60 static int g_clientIncrease = 0;
61 static std::map<int, struct GattClientWrapper> g_MapGattClient;
62 static std::mutex g_MapGattClientMutex;
63
64 #define GATTCLIENT g_MapGattClient
65
ConverWriteType(BtGattWriteType writeType)66 int ConverWriteType(BtGattWriteType writeType)
67 {
68 int outWriteType = GattCharacteristic::WriteType::DEFAULT;
69 if (writeType == OHOS_GATT_WRITE_DEFAULT) {
70 outWriteType = GattCharacteristic::WriteType::DEFAULT;
71 } else if (writeType == OHOS_GATT_WRITE_NO_RSP) {
72 outWriteType = GattCharacteristic::WriteType::NO_RESPONSE;
73 } else if (writeType == OHOS_GATT_WRITE_SIGNED) {
74 outWriteType = GattCharacteristic::WriteType::SIGNED;
75 } else {
76 HILOGE("write type: %{public}d is not supported and the default type is used.", writeType);
77 outWriteType = GattCharacteristic::WriteType::DEFAULT;
78 }
79 return outWriteType;
80 }
81
GattcFindCharacteristic(int clientId,std::shared_ptr<GattClient> & client,BtGattCharacteristic characteristic)82 static GattCharacteristic *GattcFindCharacteristic(int clientId, std::shared_ptr<GattClient> &client,
83 BtGattCharacteristic characteristic)
84 {
85 std::lock_guard<std::mutex> lock(g_MapGattClientMutex);
86 ClientIterator iter = GATTCLIENT.find(clientId);
87 if (iter == GATTCLIENT.end()) {
88 HILOGE("clientId: %{public}d, has not been registered.", clientId);
89 return nullptr;
90 }
91
92 client = iter->second.gattClient;
93 if (client == nullptr) {
94 HILOGE("client is null.");
95 return nullptr;
96 }
97
98 string strUuidSvc(characteristic.serviceUuid.uuid);
99 string strUuidChar(characteristic.characteristicUuid.uuid);
100 HILOGD("execute, strUuidSvc: %{public}s, strUuidChar: %{public}s",
101 strUuidSvc.c_str(), strUuidChar.c_str());
102 if (!regex_match(strUuidSvc, uuidRegex) || (!regex_match(strUuidChar, uuidRegex))) {
103 HILOGE("match the UUID faild.");
104 return nullptr;
105 }
106 std::optional<std::reference_wrapper<GattService>> service = client->GetService(UUID::FromString(strUuidSvc));
107 if (service == std::nullopt) {
108 HILOGE("find service fail.");
109 return nullptr;
110 }
111 GattCharacteristic *charac = service->get().GetCharacteristic(UUID::FromString(strUuidChar));
112 if (charac == nullptr) {
113 HILOGE("find characteristic fail.");
114 }
115 return charac;
116 }
117
118
119 class GattClientCallbackWrapper : public GattClientCallback {
120 public:
GattClientCallbackWrapper(BtGattClientCallbacks * callback,int clientId)121 GattClientCallbackWrapper(BtGattClientCallbacks *callback, int clientId)
122 {
123 appCallback_ = callback;
124 clientId_ = clientId;
125 }
126
OnConnectionStateChanged(int connectionState,int ret)127 void OnConnectionStateChanged(int connectionState, int ret) override
128 {
129 if (appCallback_ == nullptr || appCallback_->ConnectionStateCb == nullptr) {
130 HILOGI("callback is null.");
131 return;
132 }
133
134 HILOGD("clientId: %{public}d, connectionState: %{public}d, ret: %{public}d",
135 clientId_, connectionState, ret);
136 if (connectionState == static_cast<int>(BTConnectState::CONNECTED)) {
137 HILOGI("GattcOnConnectionStateChanged Connected, clientId: %{public}d", clientId_);
138 }
139 appCallback_->ConnectionStateCb(clientId_, connectionState, GetGattcResult(ret));
140 }
141
OnConnectionParameterChanged(int interval,int latency,int timeout,int status)142 void OnConnectionParameterChanged(int interval, int latency, int timeout, int status) override
143 {
144 if (appCallback_ == nullptr || appCallback_->connectParaUpdateCb == nullptr) {
145 HILOGI("callback is null.");
146 return;
147 }
148
149 HILOGI("clientId: %{public}d, status: %{public}d, interval: %{public}d, latency: %{public}d, "
150 "timeout: %{public}d", clientId_, status, interval, latency, timeout);
151 appCallback_->connectParaUpdateCb(clientId_, interval, latency, timeout, GetGattcResult(status));
152 }
153
OnServicesDiscovered(int status)154 void OnServicesDiscovered(int status) override
155 {
156 if (appCallback_ == nullptr || appCallback_->searchServiceCompleteCb == nullptr) {
157 HILOGI("callback is null.");
158 return;
159 }
160
161 HILOGI("GattcOnServicesDiscovered complete, clientId: %{public}d, status: %{public}d", clientId_, status);
162 appCallback_->searchServiceCompleteCb(clientId_, GetGattcResult(status));
163 }
164
OnCharacteristicReadResult(const GattCharacteristic & characteristic,int ret)165 void OnCharacteristicReadResult(const GattCharacteristic &characteristic, int ret) override
166 {
167 if (appCallback_ == nullptr || appCallback_->readCharacteristicCb == nullptr) {
168 HILOGI("callback is null.");
169 return;
170 }
171 if (characteristic.GetService() == nullptr) {
172 HILOGE("get service null.");
173 return;
174 }
175
176 BtGattReadData characData;
177 string srvUuid = characteristic.GetService()->GetUuid().ToString();
178 string charcUuid = characteristic.GetUuid().ToString();
179 GattcBuildUuid(&characData.attribute.characteristic.serviceUuid, srvUuid);
180 GattcBuildUuid(&characData.attribute.characteristic.characteristicUuid, charcUuid);
181 size_t tmpLen = 0;
182 characData.data = characteristic.GetValue(&tmpLen).get();
183 characData.dataLen = (unsigned short)tmpLen;
184
185 HILOGI("clientId: %{public}d, ret: %{public}d, dataLen: %{public}d",
186 clientId_, ret, characData.dataLen);
187 HILOGI("srvUuid: %{public}s, charcUuid: %{public}s",
188 srvUuid.c_str(), charcUuid.c_str());
189 appCallback_->readCharacteristicCb(clientId_, &characData, GetGattcResult(ret));
190 }
191
OnCharacteristicWriteResult(const GattCharacteristic & characteristic,int ret)192 void OnCharacteristicWriteResult(const GattCharacteristic &characteristic, int ret) override
193 {
194 if (appCallback_ == nullptr || appCallback_->writeCharacteristicCb == nullptr) {
195 HILOGI("callback is null.");
196 return;
197 }
198 if (characteristic.GetService() == nullptr) {
199 HILOGE("get service null.");
200 return;
201 }
202
203 BtGattCharacteristic tmpCharac;
204 string srvUuid = characteristic.GetService()->GetUuid().ToString();
205 string charcUuid = characteristic.GetUuid().ToString();
206 GattcBuildUuid(&tmpCharac.serviceUuid, srvUuid);
207 GattcBuildUuid(&tmpCharac.characteristicUuid, charcUuid);
208
209 HILOGI("clientId: %{public}d, ret: %{public}d, ", clientId_, ret);
210 HILOGI("srvUuid: %{public}s, charcUuid: %{public}s", srvUuid.c_str(), charcUuid.c_str());
211 appCallback_->writeCharacteristicCb(clientId_, &tmpCharac, GetGattcResult(ret));
212 }
213
OnDescriptorReadResult(const GattDescriptor & descriptor,int ret)214 void OnDescriptorReadResult(const GattDescriptor &descriptor, int ret) override
215 {
216 if (appCallback_ == nullptr || appCallback_->readDescriptorCb == nullptr) {
217 HILOGI("callback is null.");
218 return;
219 }
220
221 if (descriptor.GetCharacteristic() == nullptr ||
222 descriptor.GetCharacteristic()->GetService() == nullptr) {
223 HILOGE("get characteristic or service null.");
224 return;
225 }
226
227 BtGattReadData descData;
228 string srvUuid = descriptor.GetCharacteristic()->GetService()->GetUuid().ToString();
229 string charcUuid = descriptor.GetCharacteristic()->GetUuid().ToString();
230 string descUuid = descriptor.GetUuid().ToString();
231 GattcBuildUuid(&descData.attribute.descriptor.characteristic.serviceUuid, srvUuid);
232 GattcBuildUuid(&descData.attribute.descriptor.characteristic.characteristicUuid, charcUuid);
233 GattcBuildUuid(&descData.attribute.descriptor.descriptorUuid, descUuid);
234 size_t tmpLen = 0;
235 descData.data = descriptor.GetValue(&tmpLen).get();
236 descData.dataLen = (unsigned short)tmpLen;
237
238 HILOGI("clientId: %{public}d, ret: %{public}d, dataLen: %{public}d", clientId_, ret, descData.dataLen);
239 HILOGI("srvUuid: %{public}s, charcUuid: %{public}s, descUuid: %{public}s",
240 srvUuid.c_str(), charcUuid.c_str(), descUuid.c_str());
241 appCallback_->readDescriptorCb(clientId_, &descData, GetGattcResult(ret));
242 }
243
OnDescriptorWriteResult(const GattDescriptor & descriptor,int ret)244 void OnDescriptorWriteResult(const GattDescriptor &descriptor, int ret) override
245 {
246 if (appCallback_ == nullptr || appCallback_->writeDescriptorCb == NULL) {
247 HILOGI("callback is null.");
248 return;
249 }
250
251 if (descriptor.GetCharacteristic() == nullptr ||
252 descriptor.GetCharacteristic()->GetService() == nullptr) {
253 HILOGE("get characteristic or service null.");
254 return;
255 }
256
257 BtGattDescriptor tmpDesc;
258 string srvUuid = descriptor.GetCharacteristic()->GetService()->GetUuid().ToString();
259 string charcUuid = descriptor.GetCharacteristic()->GetUuid().ToString();
260 string descUuid = descriptor.GetUuid().ToString();
261 GattcBuildUuid(&tmpDesc.characteristic.serviceUuid, srvUuid);
262 GattcBuildUuid(&tmpDesc.characteristic.characteristicUuid, charcUuid);
263 GattcBuildUuid(&tmpDesc.descriptorUuid, descUuid);
264
265 HILOGI("clientId: %{public}d, ret: %{public}d", clientId_, ret);
266 HILOGI("srvUuid: %{public}s, charcUuid: %{public}s, descUuid: %{public}s",
267 srvUuid.c_str(), charcUuid.c_str(), descUuid.c_str());
268 appCallback_->writeDescriptorCb(clientId_, &tmpDesc, GetGattcResult(ret));
269 }
270
OnMtuUpdate(int mtu,int ret)271 void OnMtuUpdate(int mtu, int ret) override
272 {
273 if (appCallback_ == nullptr || appCallback_->configureMtuSizeCb == nullptr) {
274 HILOGI("callback is null.");
275 return;
276 }
277
278 HILOGI("clientId: %{public}d, mtu: %{public}d, ret: %{public}d", clientId_, mtu, ret);
279 appCallback_->configureMtuSizeCb(clientId_, mtu, GetGattcResult(ret));
280 }
281
OnSetNotifyCharacteristic(const GattCharacteristic & characteristic,int status)282 void OnSetNotifyCharacteristic(const GattCharacteristic &characteristic, int status) override
283 {
284 if (appCallback_ == nullptr || appCallback_->registerNotificationCb == nullptr) {
285 HILOGI("callback is null.");
286 return;
287 }
288
289 HILOGI("clientId: %{public}d, status: %{public}d", clientId_, status);
290 appCallback_->registerNotificationCb(clientId_, GetGattcResult(status));
291 }
292
OnCharacteristicChanged(const GattCharacteristic & characteristic)293 void OnCharacteristicChanged(const GattCharacteristic &characteristic) override
294 {
295 if (appCallback_ == nullptr || appCallback_->notificationCb == nullptr) {
296 HILOGI("callback is null.");
297 return;
298 }
299 if (characteristic.GetService() == nullptr) {
300 HILOGE("get service null.");
301 return;
302 }
303
304 BtGattReadData notificationData;
305 string srvUuid = characteristic.GetService()->GetUuid().ToString();
306 string charcUuid = characteristic.GetUuid().ToString();
307 GattcBuildUuid(¬ificationData.attribute.characteristic.serviceUuid, srvUuid);
308 GattcBuildUuid(¬ificationData.attribute.characteristic.characteristicUuid, charcUuid);
309 size_t tmpLen = 0;
310 notificationData.data = characteristic.GetValue(&tmpLen).get();
311 notificationData.dataLen = (unsigned short)tmpLen;
312
313 HILOGD("clientId: %{public}d, dataLen: %{public}d, ", clientId_, notificationData.dataLen);
314 HILOGD("srvUuid: %{public}s, charcUuid: %{public}s", srvUuid.c_str(), charcUuid.c_str());
315 appCallback_->notificationCb(clientId_, ¬ificationData, OHOS_BT_STATUS_SUCCESS);
316 }
317 private:
GattcBuildUuid(BtUuid * desUuid,const std::string & srcUuid)318 void GattcBuildUuid(BtUuid *desUuid, const std::string &srcUuid)
319 {
320 desUuid->uuid = (char *)srcUuid.c_str();
321 desUuid->uuidLen = srcUuid.size();
322 }
323
324 BtGattClientCallbacks *appCallback_;
325 int clientId_;
326 };
327
328 /**
329 * @brief Registers a GATT client with a specified application UUID.
330 *
331 * @param appUuid Indicates the UUID of the application for which the GATT client is to be registered.
332 * The UUID is defined by the application.
333 * @return Returns the client ID.
334 */
BleGattcRegister(BtUuid appUuid)335 int BleGattcRegister(BtUuid appUuid)
336 {
337 std::lock_guard<std::mutex> lock(g_MapGattClientMutex);
338 g_clientIncrease++;
339 struct GattClientWrapper clientWrapper;
340 clientWrapper.gattClient = nullptr;
341 clientWrapper.gattClientCallback = nullptr;
342 clientWrapper.remoteAddr = "";
343 clientWrapper.fastestConnFlag = false;
344 int clientId = g_clientIncrease;
345 GATTCLIENT.insert(std::pair<int, struct GattClientWrapper>(clientId, clientWrapper));
346 HILOGI("clientId: %{public}d", clientId);
347 return clientId;
348 }
349
350 /**
351 * @brief Unregisters a GATT client with a specified ID.
352 *
353 * @param clientId Indicates the ID of the GATT client.
354 * @return Returns the operation result status {@link BtStatus}.
355 */
BleGattcUnRegister(int clientId)356 int BleGattcUnRegister(int clientId)
357 {
358 std::lock_guard<std::mutex> lock(g_MapGattClientMutex);
359 HILOGI("clientId: %{public}d", clientId);
360 ClientIterator it = GATTCLIENT.find(clientId);
361 if (it != GATTCLIENT.end()) {
362 auto &clientWrapper = it->second;
363 if (clientWrapper.gattClient != nullptr) {
364 clientWrapper.gattClient = nullptr;
365 }
366 if (clientWrapper.gattClientCallback != nullptr) {
367 delete clientWrapper.gattClientCallback;
368 clientWrapper.gattClientCallback = nullptr;
369 }
370 GATTCLIENT.erase(it);
371 }
372 return OHOS_BT_STATUS_SUCCESS;
373 }
374
375 /**
376 * @brief Set fastest connection of the Gatt connection, add address to the accelerate connection map
377 * before create a new connection.
378 *
379 * @param clientId Indicates the ID of the GATT client.
380 * @param fastestConnFlag Indicates whether to enable the fastest connection.
381 * @return Returns the operation result status {@link BtStatus}.
382 */
BleGattcSetFastestConn(int clientId,bool fastestConnFlag)383 int BleGattcSetFastestConn(int clientId, bool fastestConnFlag)
384 {
385 std::lock_guard<std::mutex> lock(g_MapGattClientMutex);
386 HILOGI("clientId: %{public}d, fastestConnFlag: %{public}d", clientId, fastestConnFlag);
387 ClientIterator iter = GATTCLIENT.find(clientId);
388 if (iter == GATTCLIENT.end()) {
389 HILOGE("clientId: %{public}d, has not been registered.", clientId);
390 return OHOS_BT_STATUS_FAIL;
391 }
392 iter->second.fastestConnFlag = fastestConnFlag;
393 return OHOS_BT_STATUS_SUCCESS;
394 }
395
396 /**
397 * @brief Create a Gatt connection to a remote device.
398 *
399 * @param clientId Indicates the ID of the GATT client.
400 * @param bdAddr Indicates the remote device's address.
401 * @param isAutoConnect Indicates whether it is a direct connection(false) or a background connection(true).
402 * @param transport Indicates the transport of Gatt client {@link BtTransportType}.
403 * @return Returns the operation result status {@link BtStatus}.
404 */
BleGattcConnect(int clientId,BtGattClientCallbacks * func,const BdAddr * bdAddr,bool isAutoConnect,BtTransportType transport)405 int BleGattcConnect(int clientId, BtGattClientCallbacks *func, const BdAddr *bdAddr,
406 bool isAutoConnect, BtTransportType transport)
407 {
408 std::lock_guard<std::mutex> lock(g_MapGattClientMutex);
409 if (func == nullptr || bdAddr == nullptr) {
410 HILOGE("func or bdAddr is null.");
411 return OHOS_BT_STATUS_PARM_INVALID;
412 }
413 ClientIterator iter = GATTCLIENT.find(clientId);
414 if (iter == GATTCLIENT.end()) {
415 HILOGE("clientId: %{public}d, has not been registered.", clientId);
416 return OHOS_BT_STATUS_FAIL;
417 }
418
419 string strAddress;
420 ConvertAddr(bdAddr->addr, strAddress);
421 HILOGI("BleGattcConnect start, clientId: %{public}d, addr: %{public}s, isAutoConnect: %{public}d",
422 clientId, GetEncryptAddr(strAddress).c_str(), isAutoConnect);
423 std::shared_ptr<GattClient> client = nullptr;
424 if (iter->second.gattClient != nullptr && iter->second.remoteAddr == strAddress) {
425 HILOGI("connect to the same remote device again.");
426 client = iter->second.gattClient;
427 delete iter->second.gattClientCallback;
428 iter->second.gattClientCallback = nullptr;
429 } else {
430 BluetoothRemoteDevice device(strAddress, transport);
431 client = std::make_shared<GattClient>(device);
432 client->Init();
433 }
434
435 if (iter->second.fastestConnFlag) {
436 int result = client->RequestFastestConn();
437 if (result != OHOS_BT_STATUS_SUCCESS) {
438 HILOGE("request fastest connect fail.");
439 }
440 iter->second.fastestConnFlag = false;
441 }
442
443 GattClientCallbackWrapper *clientWrapper = new GattClientCallbackWrapper(func, clientId);
444 iter->second.gattClient = client;
445 iter->second.gattClientCallback = clientWrapper;
446 iter->second.remoteAddr = strAddress;
447 int result = client->Connect(*(clientWrapper), isAutoConnect, transport);
448 HILOGI("clientId: %{public}d, result: %{public}d", clientId, result);
449 if (result != OHOS_BT_STATUS_SUCCESS) {
450 client = nullptr;
451 delete clientWrapper;
452 iter->second.gattClient = nullptr;
453 iter->second.gattClientCallback = nullptr;
454 iter->second.remoteAddr = "";
455 return OHOS_BT_STATUS_FAIL;
456 }
457
458 return OHOS_BT_STATUS_SUCCESS;
459 }
460
461 /**
462 * @brief Set priority of the Gatt connection.
463 *
464 * @param clientId Indicates the ID of the GATT client.
465 * @param bdAddr Indicates the remote device's address.
466 * @param priority Indicates the priority of Gatt client {@link BtGattPriority}.
467 * @return Returns the operation result status {@link BtStatus}.
468 */
BleGattcSetPriority(int clientId,const BdAddr * bdAddr,BtGattPriority priority)469 int BleGattcSetPriority(int clientId, const BdAddr *bdAddr, BtGattPriority priority)
470 {
471 std::lock_guard<std::mutex> lock(g_MapGattClientMutex);
472 if (bdAddr == nullptr) {
473 HILOGE("bdAddr is null.");
474 return OHOS_BT_STATUS_PARM_INVALID;
475 }
476 ClientIterator iter = GATTCLIENT.find(clientId);
477 if (iter == GATTCLIENT.end()) {
478 HILOGE("clientId: %{public}d, has not been registered.", clientId);
479 return OHOS_BT_STATUS_FAIL;
480 }
481
482 string strAddress;
483 ConvertAddr(bdAddr->addr, strAddress);
484 HILOGI("clientId: %{public}d, addr: %{public}s, priority: %{public}d",
485 clientId, GetEncryptAddr(strAddress).c_str(), priority);
486 if (iter->second.gattClient == nullptr || iter->second.remoteAddr != strAddress) {
487 HILOGE("fail.");
488 return OHOS_BT_STATUS_FAIL;
489 }
490
491 std::shared_ptr<GattClient> client = iter->second.gattClient;
492 int result = client->RequestConnectionPriority(priority);
493 HILOGI("clientId: %{public}d, result: %{public}d", clientId, result);
494 return GetGattcResult(result);
495 }
496
497 /**
498 * @brief Disconnect a Gatt connection with a remote device.
499 *
500 * @param clientId Indicates the ID of the GATT client.
501 * @Returns the operation result status {@link BtStatus}.
502 */
BleGattcDisconnect(int clientId)503 int BleGattcDisconnect(int clientId)
504 {
505 std::lock_guard<std::mutex> lock(g_MapGattClientMutex);
506 ClientIterator iter = GATTCLIENT.find(clientId);
507 if (iter == GATTCLIENT.end()) {
508 HILOGE("clientId: %{public}d, has not been registered.", clientId);
509 return OHOS_BT_STATUS_FAIL;
510 }
511
512 std::shared_ptr<GattClient> client = iter->second.gattClient;
513 if (client == nullptr) {
514 HILOGE("clientId: %{public}d, has not been connected.", clientId);
515 return OHOS_BT_STATUS_FAIL;
516 }
517
518 int result = client->Disconnect();
519 HILOGI("clientId: %{public}d, result: %{public}d", clientId, result);
520 return GetGattcResult(result);
521 }
522
523 /**
524 * @brief Request a GATT service discovery on a remote device.
525 *
526 * @param clientId Indicates the ID of the GATT client.
527 * @return Returns the operation result status {@link BtStatus}.
528 */
BleGattcSearchServices(int clientId)529 int BleGattcSearchServices(int clientId)
530 {
531 std::lock_guard<std::mutex> lock(g_MapGattClientMutex);
532 HILOGI("BleGattcSearchServices start, clientId: %{public}d", clientId);
533 ClientIterator iter = GATTCLIENT.find(clientId);
534 if (iter == GATTCLIENT.end()) {
535 HILOGE("clientId: %{public}d, has not been registered.", clientId);
536 return OHOS_BT_STATUS_FAIL;
537 }
538
539 std::shared_ptr<GattClient> client = iter->second.gattClient;
540 if (client == nullptr) {
541 HILOGE("clientId: %{public}d, has not been connected.", clientId);
542 return OHOS_BT_STATUS_FAIL;
543 }
544
545 HILOGI("DiscoverServices() called");
546 int result = client->DiscoverServices();
547 HILOGI("clientId: %{public}d, result: %{public}d", clientId, result);
548 return GetGattcResult(result);
549 }
550
551 /**
552 * @brief Check whether the expected service exists.
553 *
554 * @param clientId Indicates the ID of the GATT client.
555 * @param serviceUuid Indicates the UUID of the service.
556 * @return Returns true or false.
557 */
BleGattcGetService(int clientId,BtUuid serviceUuid)558 bool BleGattcGetService(int clientId, BtUuid serviceUuid)
559 {
560 std::lock_guard<std::mutex> lock(g_MapGattClientMutex);
561 HILOGI("clientId: %{public}d", clientId);
562 ClientIterator iter = GATTCLIENT.find(clientId);
563 if (iter == GATTCLIENT.end()) {
564 HILOGE("clientId has not been registered.");
565 return false;
566 }
567
568 std::shared_ptr<GattClient> client = iter->second.gattClient;
569 if (client == nullptr) {
570 HILOGE("gatt is not connected.");
571 return false;
572 }
573
574 string strUuid(serviceUuid.uuid);
575 if (!regex_match(strUuid, uuidRegex)) {
576 HILOGE("match the UUID faild.");
577 return false;
578 }
579 UUID uuid(UUID::FromString(strUuid));
580 HILOGI("service uuid: %{public}s", strUuid.c_str());
581 std::optional<std::reference_wrapper<GattService>> gattService = client->GetService(uuid);
582 if (gattService == std::nullopt) {
583 HILOGE("get service failed, gattService is null.");
584 return false;
585 }
586 GattService service = gattService->get();
587 if (service.GetUuid().Equals(uuid)) {
588 HILOGI("get service success.");
589 return true;
590 } else {
591 HILOGE("get service failed, the service uuid is not exist.");
592 return false;
593 }
594 }
595
596 /**
597 * @brief Read characteristic value from the remote device.
598 *
599 * @param clientId Indicates the ID of the GATT client.
600 * @param characteristic The specified characteristic {@link BtGattCharacteristic} to be read.
601 * @return Returns the operation result status {@link BtStatus}.
602 */
BleGattcReadCharacteristic(int clientId,BtGattCharacteristic characteristic)603 int BleGattcReadCharacteristic(int clientId, BtGattCharacteristic characteristic)
604 {
605 HILOGI("clientId: %{public}d", clientId);
606 std::shared_ptr<GattClient> client = nullptr;
607 GattCharacteristic *tmpCharac = GattcFindCharacteristic(clientId, client, characteristic);
608 if (tmpCharac == nullptr || client == nullptr) {
609 HILOGE("find characteristic fail.");
610 return OHOS_BT_STATUS_FAIL;
611 }
612
613 int result = client->ReadCharacteristic(*tmpCharac);
614 HILOGI("clientId: %{public}d, result: %{public}d", clientId, result);
615 return GetGattcResult(result);
616 }
617
618 /**
619 * @brief Write characteristic value to the remote device.
620 *
621 * @param clientId Indicates the ID of the GATT client.
622 * @param characteristic The specified characteristic {@link BtGattCharacteristic} to be read.
623 * @param writeType Indicates the characteristic write type.
624 * @param value The value to be write.
625 * @param len The length of the value.
626 * @return Returns the operation result status {@link BtStatus}.
627 */
BleGattcWriteCharacteristic(int clientId,BtGattCharacteristic characteristic,BtGattWriteType writeType,int len,const char * value)628 int BleGattcWriteCharacteristic(int clientId, BtGattCharacteristic characteristic,
629 BtGattWriteType writeType, int len, const char *value)
630 {
631 HILOGD("clientId:%{public}d, writeType:%{public}d, len:%{public}d", clientId, writeType, len);
632 std::shared_ptr<GattClient> client = nullptr;
633 GattCharacteristic *tmpCharac = GattcFindCharacteristic(clientId, client, characteristic);
634 if (tmpCharac == nullptr || client == nullptr) {
635 HILOGE("find characteristic fail.");
636 return OHOS_BT_STATUS_FAIL;
637 }
638
639 int newWriteType = ConverWriteType(writeType);
640 tmpCharac->SetWriteType(newWriteType);
641 std::vector<uint8_t> characterValue(value, value + len);
642 int result = client->WriteCharacteristic(*tmpCharac, std::move(characterValue));
643 HILOGI("clientId: %{public}d, result: %{public}d", clientId, result);
644 return GetGattcResult(result);
645 }
646
647 /**
648 * @brief Read descriptor value from the remote device.
649 *
650 * @param clientId Indicates the ID of the GATT client.
651 * @param descriptor The specified characteristic {@link BtGattDescriptor} to be read.
652 * @return Returns the operation result status {@link BtStatus}.
653 */
BleGattcReadDescriptor(int clientId,BtGattDescriptor descriptor)654 int BleGattcReadDescriptor(int clientId, BtGattDescriptor descriptor)
655 {
656 HILOGI("clientId: %{public}d", clientId);
657 std::shared_ptr<GattClient> client = nullptr;
658 GattCharacteristic *tmpCharac = GattcFindCharacteristic(clientId, client, descriptor.characteristic);
659 if (tmpCharac == nullptr || client == nullptr) {
660 HILOGE("find characteristic fail.");
661 return OHOS_BT_STATUS_FAIL;
662 }
663
664 string strUuidDesc(descriptor.descriptorUuid.uuid);
665 if (!regex_match(strUuidDesc, uuidRegex)) {
666 HILOGE("match the UUID faild.");
667 return OHOS_BT_STATUS_PARM_INVALID;
668 }
669 GattDescriptor *tmpDescriptor = tmpCharac->GetDescriptor(UUID::FromString(strUuidDesc));
670 if (tmpDescriptor == nullptr) {
671 HILOGE("find descriptor fail.");
672 return OHOS_BT_STATUS_FAIL;
673 }
674
675 int result = client->ReadDescriptor(*tmpDescriptor);
676 HILOGI("clientId: %{public}d, result: %{public}d", clientId, result);
677 return GetGattcResult(result);
678 }
679
680 /**
681 * @brief Write descriptor value to the remote device.
682 *
683 * @param clientId Indicates the ID of the GATT client.
684 * @param descriptor The specified descriptor {@link BtGattDescriptor} to be read.
685 * @param value The value to be write.
686 * @param len The length of the value.
687 * @return Returns the operation result status {@link BtStatus}.
688 */
BleGattcWriteDescriptor(int clientId,BtGattDescriptor descriptor,int len,const char * value)689 int BleGattcWriteDescriptor(int clientId, BtGattDescriptor descriptor, int len, const char *value)
690 {
691 HILOGI("clientId:%{public}d, len:%{public}d", clientId, len);
692 std::shared_ptr<GattClient> client = nullptr;
693 GattCharacteristic *tmpCharac = GattcFindCharacteristic(clientId, client, descriptor.characteristic);
694 if (tmpCharac == nullptr || client == nullptr) {
695 HILOGE("find characteristic fail.");
696 return OHOS_BT_STATUS_FAIL;
697 }
698
699 string strUuidDesc(descriptor.descriptorUuid.uuid);
700 if (!regex_match(strUuidDesc, uuidRegex)) {
701 HILOGE("match the UUID faild.");
702 return OHOS_BT_STATUS_PARM_INVALID;
703 }
704 GattDescriptor *tmpDescriptor = tmpCharac->GetDescriptor(UUID::FromString(strUuidDesc));
705 if (tmpDescriptor == nullptr) {
706 HILOGE("find descriptor fail.");
707 return OHOS_BT_STATUS_FAIL;
708 }
709
710 tmpDescriptor->SetValue(reinterpret_cast<unsigned char *>(const_cast<char *>(value)), len);
711 int result = client->WriteDescriptor(*tmpDescriptor);
712 HILOGI("clientId: %{public}d, result: %{public}d", clientId, result);
713 return GetGattcResult(result);
714 }
715
716 /**
717 * @brief Configure the ATT MTU size.
718 *
719 * @param clientId Indicates the ID of the GATT client.
720 * @param mtuSize The size of MTU.
721 * @return Returns the operation result status {@link BtStatus}.
722 */
BleGattcConfigureMtuSize(int clientId,int mtuSize)723 int BleGattcConfigureMtuSize(int clientId, int mtuSize)
724 {
725 std::lock_guard<std::mutex> lock(g_MapGattClientMutex);
726 HILOGI("clientId:%{public}d, mtuSize:%{public}d", clientId, mtuSize);
727 ClientIterator iter = GATTCLIENT.find(clientId);
728 if (iter == GATTCLIENT.end()) {
729 HILOGE("GattcFindCharacteristic, clientId: %{public}d, has not been registered.", clientId);
730 return OHOS_BT_STATUS_FAIL;
731 }
732
733 std::shared_ptr<GattClient> client = iter->second.gattClient;
734 if (client == nullptr) {
735 HILOGE("client is null.");
736 return OHOS_BT_STATUS_FAIL;
737 }
738
739 int result = client->RequestBleMtuSize(mtuSize);
740 HILOGD("clientId: %{public}d, result: %{public}d", clientId, result);
741 return GetGattcResult(result);
742 }
743
744 /**
745 * @brief Enable or disable notifications for a given characteristic.
746 *
747 * @param clientId Indicates the ID of the GATT client.
748 * @param characteristic The specified characteristic {@link BtGattCharacteristic}.
749 * @param enable True or false.
750 * @return Returns the operation result status {@link BtStatus}.
751 */
BleGattcRegisterNotification(int clientId,BtGattCharacteristic characteristic,bool enable)752 int BleGattcRegisterNotification(int clientId, BtGattCharacteristic characteristic, bool enable)
753 {
754 HILOGI("clientId:%{public}d, enable:%{public}d", clientId, enable);
755 std::shared_ptr<GattClient> client = nullptr;
756 GattCharacteristic *tmpCharac = GattcFindCharacteristic(clientId, client, characteristic);
757 if (tmpCharac == nullptr || client == nullptr) {
758 HILOGE("find characteristic fail.");
759 return OHOS_BT_STATUS_FAIL;
760 }
761
762 int result = client->SetNotifyCharacteristic(*tmpCharac, enable);
763 HILOGI("clientId: %{public}d, result: %{public}d", clientId, result);
764 return GetGattcResult(result);
765 }
766 } // namespace Bluetooth
767 } // namespace OHOS
768 #ifdef __cplusplus
769 }
770 #endif
771 /** @} */