• 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     std::shared_ptr<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             clientWrapper.gattClientCallback = nullptr;
368         }
369         GATTCLIENT.erase(it);
370     }
371     return OHOS_BT_STATUS_SUCCESS;
372 }
373 
374 /**
375  * @brief Set fastest connection of the Gatt connection, add address to the accelerate connection map
376  *  before create a new connection.
377  *
378  * @param clientId Indicates the ID of the GATT client.
379  * @param fastestConnFlag Indicates whether to enable the fastest connection.
380  * @return Returns the operation result status {@link BtStatus}.
381  */
BleGattcSetFastestConn(int clientId,bool fastestConnFlag)382 int BleGattcSetFastestConn(int clientId, bool fastestConnFlag)
383 {
384     std::lock_guard<std::mutex> lock(g_MapGattClientMutex);
385     HILOGI("clientId: %{public}d, fastestConnFlag: %{public}d", clientId, fastestConnFlag);
386     ClientIterator iter = GATTCLIENT.find(clientId);
387     if (iter == GATTCLIENT.end()) {
388         HILOGE("clientId: %{public}d, has not been registered.", clientId);
389         return OHOS_BT_STATUS_FAIL;
390     }
391     iter->second.fastestConnFlag = fastestConnFlag;
392     return OHOS_BT_STATUS_SUCCESS;
393 }
394 
395 /**
396  * @brief Create a Gatt connection to a remote device.
397  *
398  * @param clientId Indicates the ID of the GATT client.
399  * @param bdAddr Indicates the remote device's address.
400  * @param isAutoConnect Indicates whether it is a direct connection(false) or a background connection(true).
401  * @param transport Indicates the transport of Gatt client {@link BtTransportType}.
402  * @return Returns the operation result status {@link BtStatus}.
403  */
BleGattcConnect(int clientId,BtGattClientCallbacks * func,const BdAddr * bdAddr,bool isAutoConnect,BtTransportType transport)404 int BleGattcConnect(int clientId, BtGattClientCallbacks *func, const BdAddr *bdAddr,
405     bool isAutoConnect, BtTransportType transport)
406 {
407     std::lock_guard<std::mutex> lock(g_MapGattClientMutex);
408     if (func == nullptr || bdAddr == nullptr) {
409         HILOGE("func or bdAddr is null.");
410         return OHOS_BT_STATUS_PARM_INVALID;
411     }
412     ClientIterator iter = GATTCLIENT.find(clientId);
413     if (iter == GATTCLIENT.end()) {
414         HILOGE("clientId: %{public}d, has not been registered.", clientId);
415         return OHOS_BT_STATUS_FAIL;
416     }
417 
418     string strAddress;
419     ConvertAddr(bdAddr->addr, strAddress);
420     HILOGI("BleGattcConnect start, clientId: %{public}d, addr: %{public}s, isAutoConnect: %{public}d",
421         clientId, GetEncryptAddr(strAddress).c_str(), isAutoConnect);
422     std::shared_ptr<GattClient> client = nullptr;
423     if (iter->second.gattClient != nullptr && iter->second.remoteAddr == strAddress) {
424         HILOGI("connect to the same remote device again.");
425         client = iter->second.gattClient;
426         iter->second.gattClientCallback = nullptr;
427     } else {
428         BluetoothRemoteDevice device(strAddress, transport);
429         client = std::make_shared<GattClient>(device);
430         client->Init();
431     }
432 
433     if (iter->second.fastestConnFlag) {
434         int result = client->RequestFastestConn();
435         if (result != OHOS_BT_STATUS_SUCCESS) {
436             HILOGE("request fastest connect fail.");
437         }
438         iter->second.fastestConnFlag = false;
439     }
440 
441     std::shared_ptr<GattClientCallbackWrapper> clientWrapper = std::make_shared<GattClientCallbackWrapper>(
442         func, clientId);
443     iter->second.gattClient = client;
444     iter->second.gattClientCallback = clientWrapper;
445     iter->second.remoteAddr = strAddress;
446     int result = client->Connect(clientWrapper, isAutoConnect, transport);
447     HILOGI("clientId: %{public}d, result: %{public}d", clientId, result);
448     if (result != OHOS_BT_STATUS_SUCCESS) {
449         client = nullptr;
450         clientWrapper = nullptr;
451         iter->second.gattClient = nullptr;
452         iter->second.gattClientCallback = nullptr;
453         iter->second.remoteAddr = "";
454         return OHOS_BT_STATUS_FAIL;
455     }
456 
457     return OHOS_BT_STATUS_SUCCESS;
458 }
459 
460 /**
461  * @brief Set priority of the Gatt connection.
462  *
463  * @param clientId Indicates the ID of the GATT client.
464  * @param bdAddr Indicates the remote device's address.
465  * @param priority Indicates the priority of Gatt client {@link BtGattPriority}.
466  * @return Returns the operation result status {@link BtStatus}.
467  */
BleGattcSetPriority(int clientId,const BdAddr * bdAddr,BtGattPriority priority)468 int BleGattcSetPriority(int clientId, const BdAddr *bdAddr, BtGattPriority priority)
469 {
470     std::lock_guard<std::mutex> lock(g_MapGattClientMutex);
471     if (bdAddr == nullptr) {
472         HILOGE("bdAddr is null.");
473         return OHOS_BT_STATUS_PARM_INVALID;
474     }
475     ClientIterator iter = GATTCLIENT.find(clientId);
476     if (iter == GATTCLIENT.end()) {
477         HILOGE("clientId: %{public}d, has not been registered.", clientId);
478         return OHOS_BT_STATUS_FAIL;
479     }
480 
481     string strAddress;
482     ConvertAddr(bdAddr->addr, strAddress);
483     HILOGI("clientId: %{public}d, addr: %{public}s, priority: %{public}d",
484         clientId, GetEncryptAddr(strAddress).c_str(), priority);
485     if (iter->second.gattClient == nullptr || iter->second.remoteAddr != strAddress) {
486         HILOGE("fail.");
487         return OHOS_BT_STATUS_FAIL;
488     }
489 
490     std::shared_ptr<GattClient> client = iter->second.gattClient;
491     int result = client->RequestConnectionPriority(priority);
492     HILOGI("clientId: %{public}d, result: %{public}d", clientId, result);
493     return GetGattcResult(result);
494 }
495 
496 /**
497  * @brief Disconnect a Gatt connection with a remote device.
498  *
499  * @param clientId Indicates the ID of the GATT client.
500  * @Returns the operation result status {@link BtStatus}.
501  */
BleGattcDisconnect(int clientId)502 int BleGattcDisconnect(int clientId)
503 {
504     std::lock_guard<std::mutex> lock(g_MapGattClientMutex);
505     ClientIterator iter = GATTCLIENT.find(clientId);
506     if (iter == GATTCLIENT.end()) {
507         HILOGE("clientId: %{public}d, has not been registered.", clientId);
508         return OHOS_BT_STATUS_FAIL;
509     }
510 
511     std::shared_ptr<GattClient> client = iter->second.gattClient;
512     if (client == nullptr) {
513         HILOGE("clientId: %{public}d, has not been connected.", clientId);
514         return OHOS_BT_STATUS_FAIL;
515     }
516 
517     int result = client->Disconnect();
518     HILOGI("clientId: %{public}d, result: %{public}d", clientId, result);
519     return GetGattcResult(result);
520 }
521 
522 /**
523  * @brief Request a GATT service discovery on a remote device.
524  *
525  * @param clientId Indicates the ID of the GATT client.
526  * @return Returns the operation result status {@link BtStatus}.
527  */
BleGattcSearchServices(int clientId)528 int BleGattcSearchServices(int clientId)
529 {
530     std::lock_guard<std::mutex> lock(g_MapGattClientMutex);
531     HILOGI("BleGattcSearchServices start, clientId: %{public}d", clientId);
532     ClientIterator iter = GATTCLIENT.find(clientId);
533     if (iter == GATTCLIENT.end()) {
534         HILOGE("clientId: %{public}d, has not been registered.", clientId);
535         return OHOS_BT_STATUS_FAIL;
536     }
537 
538     std::shared_ptr<GattClient> client = iter->second.gattClient;
539     if (client == nullptr) {
540         HILOGE("clientId: %{public}d, has not been connected.", clientId);
541         return OHOS_BT_STATUS_FAIL;
542     }
543 
544     HILOGI("DiscoverServices() called");
545     int result = client->DiscoverServices();
546     HILOGI("clientId: %{public}d, result: %{public}d", clientId, result);
547     return GetGattcResult(result);
548 }
549 
550 /**
551  * @brief Check whether the expected service exists.
552  *
553  * @param clientId Indicates the ID of the GATT client.
554  * @param serviceUuid Indicates the UUID of the service.
555  * @return Returns true or false.
556  */
BleGattcGetService(int clientId,BtUuid serviceUuid)557 bool BleGattcGetService(int clientId, BtUuid serviceUuid)
558 {
559     std::lock_guard<std::mutex> lock(g_MapGattClientMutex);
560     HILOGI("clientId: %{public}d", clientId);
561     ClientIterator iter = GATTCLIENT.find(clientId);
562     if (iter == GATTCLIENT.end()) {
563         HILOGE("clientId has not been registered.");
564         return false;
565     }
566 
567     std::shared_ptr<GattClient> client = iter->second.gattClient;
568     if (client == nullptr) {
569         HILOGE("gatt is not connected.");
570         return false;
571     }
572 
573     string strUuid(serviceUuid.uuid);
574     if (!regex_match(strUuid, uuidRegex)) {
575         HILOGE("match the UUID faild.");
576         return false;
577     }
578     UUID uuid(UUID::FromString(strUuid));
579     HILOGI("service uuid: %{public}s", strUuid.c_str());
580     std::optional<std::reference_wrapper<GattService>> gattService = client->GetService(uuid);
581     if (gattService == std::nullopt) {
582         HILOGE("get service failed, gattService is null.");
583         return false;
584     }
585     GattService service = gattService->get();
586     if (service.GetUuid().Equals(uuid)) {
587         HILOGI("get service success.");
588         return true;
589     } else {
590         HILOGE("get service failed, the service uuid is not exist.");
591         return false;
592     }
593 }
594 
595 /**
596  * @brief Read characteristic value from the remote device.
597  *
598  * @param clientId Indicates the ID of the GATT client.
599  * @param characteristic The specified characteristic {@link BtGattCharacteristic} to be read.
600  * @return Returns the operation result status {@link BtStatus}.
601  */
BleGattcReadCharacteristic(int clientId,BtGattCharacteristic characteristic)602 int BleGattcReadCharacteristic(int clientId, BtGattCharacteristic characteristic)
603 {
604     HILOGI("clientId: %{public}d", clientId);
605     std::shared_ptr<GattClient> client = nullptr;
606     GattCharacteristic *tmpCharac = GattcFindCharacteristic(clientId, client, characteristic);
607     if (tmpCharac == nullptr || client == nullptr) {
608         HILOGE("find characteristic fail.");
609         return OHOS_BT_STATUS_FAIL;
610     }
611 
612     int result = client->ReadCharacteristic(*tmpCharac);
613     HILOGI("clientId: %{public}d, result: %{public}d", clientId, result);
614     return GetGattcResult(result);
615 }
616 
617 /**
618  * @brief Write characteristic value to the remote device.
619  *
620  * @param clientId Indicates the ID of the GATT client.
621  * @param characteristic The specified characteristic {@link BtGattCharacteristic} to be read.
622  * @param writeType Indicates the characteristic write type.
623  * @param value The value to be write.
624  * @param len The length of the value.
625  * @return Returns the operation result status {@link BtStatus}.
626  */
BleGattcWriteCharacteristic(int clientId,BtGattCharacteristic characteristic,BtGattWriteType writeType,int len,const char * value)627 int BleGattcWriteCharacteristic(int clientId, BtGattCharacteristic characteristic,
628     BtGattWriteType writeType, int len, const char *value)
629 {
630     HILOGD("clientId:%{public}d, writeType:%{public}d, len:%{public}d", clientId, writeType, len);
631     std::shared_ptr<GattClient> client = nullptr;
632     GattCharacteristic *tmpCharac = GattcFindCharacteristic(clientId, client, characteristic);
633     if (tmpCharac == nullptr || client == nullptr) {
634         HILOGE("find characteristic fail.");
635         return OHOS_BT_STATUS_FAIL;
636     }
637 
638     int newWriteType = ConverWriteType(writeType);
639     tmpCharac->SetWriteType(newWriteType);
640     std::vector<uint8_t> characterValue(value, value + len);
641     int result = client->WriteCharacteristic(*tmpCharac, std::move(characterValue));
642     HILOGI("clientId: %{public}d, result: %{public}d", clientId, result);
643     return GetGattcResult(result);
644 }
645 
646 /**
647  * @brief Read descriptor value from the remote device.
648  *
649  * @param clientId Indicates the ID of the GATT client.
650  * @param descriptor The specified characteristic {@link BtGattDescriptor} to be read.
651  * @return Returns the operation result status {@link BtStatus}.
652  */
BleGattcReadDescriptor(int clientId,BtGattDescriptor descriptor)653 int BleGattcReadDescriptor(int clientId, BtGattDescriptor descriptor)
654 {
655     HILOGI("clientId: %{public}d", clientId);
656     std::shared_ptr<GattClient> client = nullptr;
657     GattCharacteristic *tmpCharac = GattcFindCharacteristic(clientId, client, descriptor.characteristic);
658     if (tmpCharac == nullptr || client == nullptr) {
659         HILOGE("find characteristic fail.");
660         return OHOS_BT_STATUS_FAIL;
661     }
662 
663     string strUuidDesc(descriptor.descriptorUuid.uuid);
664     if (!regex_match(strUuidDesc, uuidRegex)) {
665         HILOGE("match the UUID faild.");
666         return OHOS_BT_STATUS_PARM_INVALID;
667     }
668     GattDescriptor *tmpDescriptor = tmpCharac->GetDescriptor(UUID::FromString(strUuidDesc));
669     if (tmpDescriptor == nullptr) {
670         HILOGE("find descriptor fail.");
671         return OHOS_BT_STATUS_FAIL;
672     }
673 
674     int result = client->ReadDescriptor(*tmpDescriptor);
675     HILOGI("clientId: %{public}d, result: %{public}d", clientId, result);
676     return GetGattcResult(result);
677 }
678 
679 /**
680  * @brief Write descriptor value to the remote device.
681  *
682  * @param clientId Indicates the ID of the GATT client.
683  * @param descriptor The specified descriptor {@link BtGattDescriptor} to be read.
684  * @param value The value to be write.
685  * @param len The length of the value.
686  * @return Returns the operation result status {@link BtStatus}.
687  */
BleGattcWriteDescriptor(int clientId,BtGattDescriptor descriptor,int len,const char * value)688 int BleGattcWriteDescriptor(int clientId, BtGattDescriptor descriptor, int len, const char *value)
689 {
690     HILOGI("clientId:%{public}d, len:%{public}d", clientId, len);
691     std::shared_ptr<GattClient> client = nullptr;
692     GattCharacteristic *tmpCharac = GattcFindCharacteristic(clientId, client, descriptor.characteristic);
693     if (tmpCharac == nullptr || client == nullptr) {
694         HILOGE("find characteristic fail.");
695         return OHOS_BT_STATUS_FAIL;
696     }
697 
698     string strUuidDesc(descriptor.descriptorUuid.uuid);
699     if (!regex_match(strUuidDesc, uuidRegex)) {
700         HILOGE("match the UUID faild.");
701         return OHOS_BT_STATUS_PARM_INVALID;
702     }
703     GattDescriptor *tmpDescriptor = tmpCharac->GetDescriptor(UUID::FromString(strUuidDesc));
704     if (tmpDescriptor == nullptr) {
705         HILOGE("find descriptor fail.");
706         return OHOS_BT_STATUS_FAIL;
707     }
708 
709     tmpDescriptor->SetValue(reinterpret_cast<unsigned char *>(const_cast<char *>(value)), len);
710     int result = client->WriteDescriptor(*tmpDescriptor);
711     HILOGI("clientId: %{public}d, result: %{public}d", clientId, result);
712     return GetGattcResult(result);
713 }
714 
715 /**
716  * @brief Configure the ATT MTU size.
717  *
718  * @param clientId Indicates the ID of the GATT client.
719  * @param mtuSize The size of MTU.
720  * @return Returns the operation result status {@link BtStatus}.
721  */
BleGattcConfigureMtuSize(int clientId,int mtuSize)722 int BleGattcConfigureMtuSize(int clientId, int mtuSize)
723 {
724     std::lock_guard<std::mutex> lock(g_MapGattClientMutex);
725     HILOGI("clientId:%{public}d, mtuSize:%{public}d", clientId, mtuSize);
726     ClientIterator iter = GATTCLIENT.find(clientId);
727     if (iter == GATTCLIENT.end()) {
728         HILOGE("GattcFindCharacteristic, clientId: %{public}d, has not been registered.", clientId);
729         return OHOS_BT_STATUS_FAIL;
730     }
731 
732     std::shared_ptr<GattClient> client = iter->second.gattClient;
733     if (client == nullptr) {
734         HILOGE("client is null.");
735         return OHOS_BT_STATUS_FAIL;
736     }
737 
738     int result = client->RequestBleMtuSize(mtuSize);
739     HILOGD("clientId: %{public}d, result: %{public}d", clientId, result);
740     return GetGattcResult(result);
741 }
742 
743 /**
744  * @brief Enable or disable notifications for a given characteristic.
745  *
746  * @param clientId Indicates the ID of the GATT client.
747  * @param characteristic The specified characteristic {@link BtGattCharacteristic}.
748  * @param enable True or false.
749  * @return Returns the operation result status {@link BtStatus}.
750  */
BleGattcRegisterNotification(int clientId,BtGattCharacteristic characteristic,bool enable)751 int BleGattcRegisterNotification(int clientId, BtGattCharacteristic characteristic, bool enable)
752 {
753     HILOGI("clientId:%{public}d, enable:%{public}d", clientId, enable);
754     std::shared_ptr<GattClient> client = nullptr;
755     GattCharacteristic *tmpCharac = GattcFindCharacteristic(clientId, client, characteristic);
756     if (tmpCharac == nullptr || client == nullptr) {
757         HILOGE("find characteristic fail.");
758         return OHOS_BT_STATUS_FAIL;
759     }
760 
761     int result = client->SetNotifyCharacteristic(*tmpCharac, enable);
762     HILOGI("clientId: %{public}d, result: %{public}d", clientId, result);
763     return GetGattcResult(result);
764 }
765 }  // namespace Bluetooth
766 }  // namespace OHOS
767 #ifdef __cplusplus
768 }
769 #endif
770 /** @} */