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(¬ificationData.attribute.characteristic.serviceUuid, srvUuid);
308 GattcBuildUuid(¬ificationData.attribute.characteristic.characteristicUuid, charcUuid);
309 size_t tmpLen = 0;
310 notificationData.data = characteristic.GetValue(&tmpLen).get();
311 notificationData.dataLen = (unsigned short)tmpLen;
312
313 HILOGD("clientId: %{public}d, dataLen: %{public}d, ", clientId_, notificationData.dataLen);
314 HILOGD("srvUuid: %{public}s, charcUuid: %{public}s", srvUuid.c_str(), charcUuid.c_str());
315 appCallback_->notificationCb(clientId_, ¬ificationData, OHOS_BT_STATUS_SUCCESS);
316 }
317 private:
GattcBuildUuid(BtUuid * desUuid,const std::string & srcUuid)318 void GattcBuildUuid(BtUuid *desUuid, const std::string &srcUuid)
319 {
320 desUuid->uuid = (char *)srcUuid.c_str();
321 desUuid->uuidLen = srcUuid.size();
322 }
323
324 BtGattClientCallbacks *appCallback_;
325 int clientId_;
326 };
327
328 /**
329 * @brief Registers a GATT client with a specified application UUID.
330 *
331 * @param appUuid Indicates the UUID of the application for which the GATT client is to be registered.
332 * The UUID is defined by the application.
333 * @return Returns the client ID.
334 */
BleGattcRegister(BtUuid appUuid)335 int BleGattcRegister(BtUuid appUuid)
336 {
337 std::lock_guard<std::mutex> lock(g_MapGattClientMutex);
338 g_clientIncrease++;
339 struct GattClientWrapper clientWrapper;
340 clientWrapper.gattClient = nullptr;
341 clientWrapper.gattClientCallback = nullptr;
342 clientWrapper.remoteAddr = "";
343 clientWrapper.fastestConnFlag = false;
344 int clientId = g_clientIncrease;
345 GATTCLIENT.insert(std::pair<int, struct GattClientWrapper>(clientId, clientWrapper));
346 HILOGI("clientId: %{public}d", clientId);
347 return clientId;
348 }
349
350 /**
351 * @brief Unregisters a GATT client with a specified ID.
352 *
353 * @param clientId Indicates the ID of the GATT client.
354 * @return Returns the operation result status {@link BtStatus}.
355 */
BleGattcUnRegister(int clientId)356 int BleGattcUnRegister(int clientId)
357 {
358 std::lock_guard<std::mutex> lock(g_MapGattClientMutex);
359 HILOGI("clientId: %{public}d", clientId);
360 ClientIterator it = GATTCLIENT.find(clientId);
361 if (it != GATTCLIENT.end()) {
362 auto &clientWrapper = it->second;
363 if (clientWrapper.gattClient != nullptr) {
364 clientWrapper.gattClient = nullptr;
365 }
366 if (clientWrapper.gattClientCallback != nullptr) {
367 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 /** @} */