• 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>
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(&notificationData.attribute.characteristic.serviceUuid, srvUuid);
308         GattcBuildUuid(&notificationData.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_, &notificationData, 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 /** @} */