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