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