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 #include <atomic>
22
23 #include "bluetooth_gatt_characteristic.h"
24 #include "bluetooth_gatt_client.h"
25 #include "bluetooth_gatt_descriptor.h"
26 #include "bluetooth_gatt_service.h"
27 #include "bluetooth_log.h"
28 #include "bluetooth_utils.h"
29 #include "bluetooth_remote_device.h"
30
31 #include "iosfwd"
32 #include "memory"
33 #include "new"
34 #include "ohos_bt_adapter_utils.h"
35 #include "ohos_bt_def.h"
36 #include "optional"
37 #include "string"
38 #include "type_traits"
39 #include "utility"
40 #include "uuid.h"
41
42 #ifdef __cplusplus
43 extern "C" {
44 #endif
45
46 using namespace std;
47
48 namespace OHOS {
49 namespace Bluetooth {
50 class GattClientCallbackWrapper;
51
52 struct GattClientWrapper {
53 std::shared_ptr<GattClient> gattClient;
54 std::shared_ptr<GattClientCallbackWrapper> gattClientCallback;
55 string remoteAddr;
56 bool fastestConnFlag;
57 };
58
59 using ClientIterator = std::map<int, struct GattClientWrapper>::iterator;
60
61 static std::atomic<int> g_clientIncrease(0);
62 static std::map<int, struct GattClientWrapper> g_MapGattClient;
63 static std::mutex g_MapGattClientMutex;
64
65 #define GATTCLIENT g_MapGattClient
66
ConverWriteType(BtGattWriteType writeType)67 int ConverWriteType(BtGattWriteType writeType)
68 {
69 int outWriteType = GattCharacteristic::WriteType::DEFAULT;
70 if (writeType == OHOS_GATT_WRITE_DEFAULT) {
71 outWriteType = GattCharacteristic::WriteType::DEFAULT;
72 } else if (writeType == OHOS_GATT_WRITE_NO_RSP) {
73 outWriteType = GattCharacteristic::WriteType::NO_RESPONSE;
74 } else if (writeType == OHOS_GATT_WRITE_SIGNED) {
75 outWriteType = GattCharacteristic::WriteType::SIGNED;
76 } else {
77 HILOGE("write type: %{public}d is not supported and the default type is used.", writeType);
78 outWriteType = GattCharacteristic::WriteType::DEFAULT;
79 }
80 return outWriteType;
81 }
82
GattcFindCharacteristic(int clientId, std::shared_ptr<GattClient> &client, BtGattCharacteristic characteristic)83 static GattCharacteristic *GattcFindCharacteristic(int clientId, std::shared_ptr<GattClient> &client,
84 BtGattCharacteristic characteristic)
85 {
86 std::lock_guard<std::mutex> lock(g_MapGattClientMutex);
87 ClientIterator iter = GATTCLIENT.find(clientId);
88 if (iter == GATTCLIENT.end()) {
89 HILOGE("clientId: %{public}d, has not been registered.", clientId);
90 return nullptr;
91 }
92
93 client = iter->second.gattClient;
94 if (client == nullptr) {
95 HILOGE("client is null.");
96 return nullptr;
97 }
98
99 string strUuidSvc(characteristic.serviceUuid.uuid);
100 string strUuidChar(characteristic.characteristicUuid.uuid);
101 HILOGD("execute, strUuidSvc: %{public}s, strUuidChar: %{public}s",
102 strUuidSvc.c_str(), strUuidChar.c_str());
103 if (!IsValidUuid(strUuidSvc) || !IsValidUuid(strUuidChar)) {
104 HILOGE("match the UUID faild.");
105 return nullptr;
106 }
107 std::optional<std::reference_wrapper<GattService>> service = client->GetService(UUID::FromString(strUuidSvc));
108 if (service == std::nullopt) {
109 HILOGE("find service fail.");
110 return nullptr;
111 }
112 GattCharacteristic *charac = service->get().GetCharacteristic(UUID::FromString(strUuidChar));
113 if (charac == nullptr) {
114 HILOGE("find characteristic fail.");
115 }
116 return charac;
117 }
118
119
120 class GattClientCallbackWrapper : public GattClientCallback {
121 public:
GattClientCallbackWrapper(BtGattClientCallbacks *callback, int clientId)122 GattClientCallbackWrapper(BtGattClientCallbacks *callback, int clientId)
123 {
124 appCallback_ = callback;
125 clientId_ = clientId;
126 }
127
128 void OnConnectionStateChanged(int connectionState, int ret) override
129 {
130 if (appCallback_ == nullptr || appCallback_->ConnectionStateCb == nullptr) {
131 HILOGI("callback is null.");
132 return;
133 }
134
135 HILOGD("clientId: %{public}d, connectionState: %{public}d, ret: %{public}d",
136 clientId_, connectionState, ret);
137 if (connectionState == static_cast<int>(BTConnectState::CONNECTED)) {
138 HILOGI("GattcOnConnectionStateChanged Connected, clientId: %{public}d", clientId_);
139 }
140 appCallback_->ConnectionStateCb(clientId_, connectionState, GetGattcResult(ret));
141 }
142
143 void OnConnectionParameterChanged(int interval, int latency, int timeout, int status) override
144 {
145 if (appCallback_ == nullptr || appCallback_->connectParaUpdateCb == nullptr) {
146 HILOGI("callback is null.");
147 return;
148 }
149
150 HILOGI("clientId: %{public}d, status: %{public}d, interval: %{public}d, latency: %{public}d, "
151 "timeout: %{public}d", clientId_, status, interval, latency, timeout);
152 appCallback_->connectParaUpdateCb(clientId_, interval, latency, timeout, GetGattcResult(status));
153 }
154
155 void OnServicesDiscovered(int status) override
156 {
157 if (appCallback_ == nullptr || appCallback_->searchServiceCompleteCb == nullptr) {
158 HILOGI("callback is null.");
159 return;
160 }
161
162 HILOGI("GattcOnServicesDiscovered complete, clientId: %{public}d, status: %{public}d", clientId_, status);
163 appCallback_->searchServiceCompleteCb(clientId_, GetGattcResult(status));
164 }
165
166 void OnCharacteristicReadResult(const GattCharacteristic &characteristic, int ret) override
167 {
168 if (appCallback_ == nullptr || appCallback_->readCharacteristicCb == nullptr) {
169 HILOGI("callback is null.");
170 return;
171 }
172 if (characteristic.GetService() == nullptr) {
173 HILOGE("get service null.");
174 return;
175 }
176
177 BtGattReadData characData;
178 string srvUuid = characteristic.GetService()->GetUuid().ToString();
179 string charcUuid = characteristic.GetUuid().ToString();
180 GattcBuildUuid(&characData.attribute.characteristic.serviceUuid, srvUuid);
181 GattcBuildUuid(&characData.attribute.characteristic.characteristicUuid, charcUuid);
182 size_t tmpLen = 0;
183 characData.data = characteristic.GetValue(&tmpLen).get();
184 characData.dataLen = (unsigned short)tmpLen;
185
186 HILOGI("clientId: %{public}d, ret: %{public}d, dataLen: %{public}d",
187 clientId_, ret, characData.dataLen);
188 HILOGI("srvUuid: %{public}s, charcUuid: %{public}s",
189 srvUuid.c_str(), charcUuid.c_str());
190 appCallback_->readCharacteristicCb(clientId_, &characData, GetGattcResult(ret));
191 }
192
193 void OnCharacteristicWriteResult(const GattCharacteristic &characteristic, int ret) override
194 {
195 if (appCallback_ == nullptr || appCallback_->writeCharacteristicCb == nullptr) {
196 HILOGI("callback is null.");
197 return;
198 }
199 if (characteristic.GetService() == nullptr) {
200 HILOGE("get service null.");
201 return;
202 }
203
204 BtGattCharacteristic tmpCharac;
205 string srvUuid = characteristic.GetService()->GetUuid().ToString();
206 string charcUuid = characteristic.GetUuid().ToString();
207 GattcBuildUuid(&tmpCharac.serviceUuid, srvUuid);
208 GattcBuildUuid(&tmpCharac.characteristicUuid, charcUuid);
209
210 HILOGI("clientId: %{public}d, ret: %{public}d, ", clientId_, ret);
211 HILOGI("srvUuid: %{public}s, charcUuid: %{public}s", srvUuid.c_str(), charcUuid.c_str());
212 appCallback_->writeCharacteristicCb(clientId_, &tmpCharac, GetGattcResult(ret));
213 }
214
215 void OnDescriptorReadResult(const GattDescriptor &descriptor, int ret) override
216 {
217 if (appCallback_ == nullptr || appCallback_->readDescriptorCb == nullptr) {
218 HILOGI("callback is null.");
219 return;
220 }
221
222 if (descriptor.GetCharacteristic() == nullptr ||
223 descriptor.GetCharacteristic()->GetService() == nullptr) {
224 HILOGE("get characteristic or service null.");
225 return;
226 }
227
228 BtGattReadData descData;
229 string srvUuid = descriptor.GetCharacteristic()->GetService()->GetUuid().ToString();
230 string charcUuid = descriptor.GetCharacteristic()->GetUuid().ToString();
231 string descUuid = descriptor.GetUuid().ToString();
232 GattcBuildUuid(&descData.attribute.descriptor.characteristic.serviceUuid, srvUuid);
233 GattcBuildUuid(&descData.attribute.descriptor.characteristic.characteristicUuid, charcUuid);
234 GattcBuildUuid(&descData.attribute.descriptor.descriptorUuid, descUuid);
235 size_t tmpLen = 0;
236 descData.data = descriptor.GetValue(&tmpLen).get();
237 descData.dataLen = (unsigned short)tmpLen;
238
239 HILOGI("clientId: %{public}d, ret: %{public}d, dataLen: %{public}d", clientId_, ret, descData.dataLen);
240 HILOGI("srvUuid: %{public}s, charcUuid: %{public}s, descUuid: %{public}s",
241 srvUuid.c_str(), charcUuid.c_str(), descUuid.c_str());
242 appCallback_->readDescriptorCb(clientId_, &descData, GetGattcResult(ret));
243 }
244
245 void OnDescriptorWriteResult(const GattDescriptor &descriptor, int ret) override
246 {
247 if (appCallback_ == nullptr || appCallback_->writeDescriptorCb == NULL) {
248 HILOGI("callback is null.");
249 return;
250 }
251
252 if (descriptor.GetCharacteristic() == nullptr ||
253 descriptor.GetCharacteristic()->GetService() == nullptr) {
254 HILOGE("get characteristic or service null.");
255 return;
256 }
257
258 BtGattDescriptor tmpDesc;
259 string srvUuid = descriptor.GetCharacteristic()->GetService()->GetUuid().ToString();
260 string charcUuid = descriptor.GetCharacteristic()->GetUuid().ToString();
261 string descUuid = descriptor.GetUuid().ToString();
262 GattcBuildUuid(&tmpDesc.characteristic.serviceUuid, srvUuid);
263 GattcBuildUuid(&tmpDesc.characteristic.characteristicUuid, charcUuid);
264 GattcBuildUuid(&tmpDesc.descriptorUuid, descUuid);
265
266 HILOGI("clientId: %{public}d, ret: %{public}d", clientId_, ret);
267 HILOGI("srvUuid: %{public}s, charcUuid: %{public}s, descUuid: %{public}s",
268 srvUuid.c_str(), charcUuid.c_str(), descUuid.c_str());
269 appCallback_->writeDescriptorCb(clientId_, &tmpDesc, GetGattcResult(ret));
270 }
271
272 void OnMtuUpdate(int mtu, int ret) override
273 {
274 if (appCallback_ == nullptr || appCallback_->configureMtuSizeCb == nullptr) {
275 HILOGI("callback is null.");
276 return;
277 }
278
279 HILOGI("clientId: %{public}d, mtu: %{public}d, ret: %{public}d", clientId_, mtu, ret);
280 appCallback_->configureMtuSizeCb(clientId_, mtu, GetGattcResult(ret));
281 }
282
283 void OnSetNotifyCharacteristic(const GattCharacteristic &characteristic, int status) override
284 {
285 if (appCallback_ == nullptr || appCallback_->registerNotificationCb == nullptr) {
286 HILOGI("callback is null.");
287 return;
288 }
289
290 HILOGI("clientId: %{public}d, status: %{public}d", clientId_, status);
291 appCallback_->registerNotificationCb(clientId_, GetGattcResult(status));
292 }
293
294 void OnCharacteristicChanged(const GattCharacteristic &characteristic) override
295 {
296 if (appCallback_ == nullptr || appCallback_->notificationCb == nullptr) {
297 HILOGI("callback is null.");
298 return;
299 }
300 if (characteristic.GetService() == nullptr) {
301 HILOGE("get service null.");
302 return;
303 }
304
305 BtGattReadData notificationData;
306 string srvUuid = characteristic.GetService()->GetUuid().ToString();
307 string charcUuid = characteristic.GetUuid().ToString();
308 GattcBuildUuid(¬ificationData.attribute.characteristic.serviceUuid, srvUuid);
309 GattcBuildUuid(¬ificationData.attribute.characteristic.characteristicUuid, charcUuid);
310 size_t tmpLen = 0;
311 notificationData.data = characteristic.GetValue(&tmpLen).get();
312 notificationData.dataLen = (unsigned short)tmpLen;
313
314 HILOGD("clientId: %{public}d, dataLen: %{public}d, ", clientId_, notificationData.dataLen);
315 HILOGD("srvUuid: %{public}s, charcUuid: %{public}s", srvUuid.c_str(), charcUuid.c_str());
316 appCallback_->notificationCb(clientId_, ¬ificationData, OHOS_BT_STATUS_SUCCESS);
317 }
318 private:
GattcBuildUuid(BtUuid *desUuid, const std::string &srcUuid)319 void GattcBuildUuid(BtUuid *desUuid, const std::string &srcUuid)
320 {
321 desUuid->uuid = (char *)srcUuid.c_str();
322 desUuid->uuidLen = srcUuid.size();
323 }
324
325 BtGattClientCallbacks *appCallback_;
326 int clientId_;
327 };
328
329 /**
330 * @brief Registers a GATT client with a specified application UUID.
331 *
332 * @param appUuid Indicates the UUID of the application for which the GATT client is to be registered.
333 * The UUID is defined by the application.
334 * @return Returns the client ID.
335 */
BleGattcRegister(BtUuid appUuid)336 int BleGattcRegister(BtUuid appUuid)
337 {
338 std::lock_guard<std::mutex> lock(g_MapGattClientMutex);
339 g_clientIncrease++;
340 struct GattClientWrapper clientWrapper;
341 clientWrapper.gattClient = nullptr;
342 clientWrapper.gattClientCallback = nullptr;
343 clientWrapper.remoteAddr = "";
344 clientWrapper.fastestConnFlag = false;
345 int clientId = g_clientIncrease.load();
346 GATTCLIENT.insert(std::pair<int, struct GattClientWrapper>(clientId, clientWrapper));
347 HILOGI("clientId: %{public}d", clientId);
348 return clientId;
349 }
350
351 /**
352 * @brief Unregisters a GATT client with a specified ID.
353 *
354 * @param clientId Indicates the ID of the GATT client.
355 * @return Returns the operation result status {@link BtStatus}.
356 */
BleGattcUnRegister(int clientId)357 int BleGattcUnRegister(int clientId)
358 {
359 std::lock_guard<std::mutex> lock(g_MapGattClientMutex);
360 HILOGI("clientId: %{public}d", clientId);
361 ClientIterator it = GATTCLIENT.find(clientId);
362 if (it != GATTCLIENT.end()) {
363 auto &clientWrapper = it->second;
364 if (clientWrapper.gattClient != nullptr) {
365 clientWrapper.gattClient = nullptr;
366 }
367 if (clientWrapper.gattClientCallback != nullptr) {
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 iter->second.gattClientCallback = nullptr;
428 } else {
429 BluetoothRemoteDevice device(strAddress, transport);
430 client = std::make_shared<GattClient>(device);
431 client->Init();
432 }
433
434 if (iter->second.fastestConnFlag) {
435 int result = client->RequestFastestConn();
436 if (result != OHOS_BT_STATUS_SUCCESS) {
437 HILOGE("request fastest connect fail.");
438 }
439 iter->second.fastestConnFlag = false;
440 }
441
442 std::shared_ptr<GattClientCallbackWrapper> clientWrapper = std::make_shared<GattClientCallbackWrapper>(
443 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 clientWrapper = nullptr;
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 (!IsValidUuid(strUuid)) {
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 if (writeType != OHOS_GATT_WRITE_TYPE_UNKNOWN) {
640 int newWriteType = ConverWriteType(writeType);
641 tmpCharac->SetWriteType(newWriteType);
642 }
643
644 std::vector<uint8_t> characterValue(value, value + len);
645 int result = client->WriteCharacteristic(*tmpCharac, std::move(characterValue));
646 HILOGD("clientId: %{public}d, result: %{public}d", clientId, result);
647 return GetGattcResult(result);
648 }
649
650 /**
651 * @brief Read descriptor value from the remote device.
652 *
653 * @param clientId Indicates the ID of the GATT client.
654 * @param descriptor The specified characteristic {@link BtGattDescriptor} to be read.
655 * @return Returns the operation result status {@link BtStatus}.
656 */
BleGattcReadDescriptor(int clientId, BtGattDescriptor descriptor)657 int BleGattcReadDescriptor(int clientId, BtGattDescriptor descriptor)
658 {
659 HILOGI("clientId: %{public}d", clientId);
660 std::shared_ptr<GattClient> client = nullptr;
661 GattCharacteristic *tmpCharac = GattcFindCharacteristic(clientId, client, descriptor.characteristic);
662 if (tmpCharac == nullptr || client == nullptr) {
663 HILOGE("find characteristic fail.");
664 return OHOS_BT_STATUS_FAIL;
665 }
666
667 string strUuidDesc(descriptor.descriptorUuid.uuid);
668 if (!IsValidUuid(strUuidDesc)) {
669 HILOGE("match the UUID faild.");
670 return OHOS_BT_STATUS_PARM_INVALID;
671 }
672 GattDescriptor *tmpDescriptor = tmpCharac->GetDescriptor(UUID::FromString(strUuidDesc));
673 if (tmpDescriptor == nullptr) {
674 HILOGE("find descriptor fail.");
675 return OHOS_BT_STATUS_FAIL;
676 }
677
678 int result = client->ReadDescriptor(*tmpDescriptor);
679 HILOGI("clientId: %{public}d, result: %{public}d", clientId, result);
680 return GetGattcResult(result);
681 }
682
683 /**
684 * @brief Write descriptor value to the remote device.
685 *
686 * @param clientId Indicates the ID of the GATT client.
687 * @param descriptor The specified descriptor {@link BtGattDescriptor} to be read.
688 * @param value The value to be write.
689 * @param len The length of the value.
690 * @return Returns the operation result status {@link BtStatus}.
691 */
BleGattcWriteDescriptor(int clientId, BtGattDescriptor descriptor, int len, const char *value)692 int BleGattcWriteDescriptor(int clientId, BtGattDescriptor descriptor, int len, const char *value)
693 {
694 HILOGI("clientId:%{public}d, len:%{public}d", clientId, len);
695 std::shared_ptr<GattClient> client = nullptr;
696 GattCharacteristic *tmpCharac = GattcFindCharacteristic(clientId, client, descriptor.characteristic);
697 if (tmpCharac == nullptr || client == nullptr) {
698 HILOGE("find characteristic fail.");
699 return OHOS_BT_STATUS_FAIL;
700 }
701
702 string strUuidDesc(descriptor.descriptorUuid.uuid);
703 if (!IsValidUuid(strUuidDesc)) {
704 HILOGE("match the UUID faild.");
705 return OHOS_BT_STATUS_PARM_INVALID;
706 }
707 GattDescriptor *tmpDescriptor = tmpCharac->GetDescriptor(UUID::FromString(strUuidDesc));
708 if (tmpDescriptor == nullptr) {
709 HILOGE("find descriptor fail.");
710 return OHOS_BT_STATUS_FAIL;
711 }
712
713 tmpDescriptor->SetValue(reinterpret_cast<unsigned char *>(const_cast<char *>(value)), len);
714 int result = client->WriteDescriptor(*tmpDescriptor);
715 HILOGI("clientId: %{public}d, result: %{public}d", clientId, result);
716 return GetGattcResult(result);
717 }
718
719 /**
720 * @brief Configure the ATT MTU size.
721 *
722 * @param clientId Indicates the ID of the GATT client.
723 * @param mtuSize The size of MTU.
724 * @return Returns the operation result status {@link BtStatus}.
725 */
BleGattcConfigureMtuSize(int clientId, int mtuSize)726 int BleGattcConfigureMtuSize(int clientId, int mtuSize)
727 {
728 std::lock_guard<std::mutex> lock(g_MapGattClientMutex);
729 HILOGI("clientId:%{public}d, mtuSize:%{public}d", clientId, mtuSize);
730 ClientIterator iter = GATTCLIENT.find(clientId);
731 if (iter == GATTCLIENT.end()) {
732 HILOGE("GattcFindCharacteristic, clientId: %{public}d, has not been registered.", clientId);
733 return OHOS_BT_STATUS_FAIL;
734 }
735
736 std::shared_ptr<GattClient> client = iter->second.gattClient;
737 if (client == nullptr) {
738 HILOGE("client is null.");
739 return OHOS_BT_STATUS_FAIL;
740 }
741
742 int result = client->RequestBleMtuSize(mtuSize);
743 HILOGD("clientId: %{public}d, result: %{public}d", clientId, result);
744 return GetGattcResult(result);
745 }
746
747 /**
748 * @brief Enable or disable notifications for a given characteristic.
749 *
750 * @param clientId Indicates the ID of the GATT client.
751 * @param characteristic The specified characteristic {@link BtGattCharacteristic}.
752 * @param enable True or false.
753 * @return Returns the operation result status {@link BtStatus}.
754 */
BleGattcRegisterNotification(int clientId, BtGattCharacteristic characteristic, bool enable)755 int BleGattcRegisterNotification(int clientId, BtGattCharacteristic characteristic, bool enable)
756 {
757 HILOGI("clientId:%{public}d, enable:%{public}d", clientId, enable);
758 std::shared_ptr<GattClient> client = nullptr;
759 GattCharacteristic *tmpCharac = GattcFindCharacteristic(clientId, client, characteristic);
760 if (tmpCharac == nullptr || client == nullptr) {
761 HILOGE("find characteristic fail.");
762 return OHOS_BT_STATUS_FAIL;
763 }
764
765 int result = client->SetNotifyCharacteristic(*tmpCharac, enable);
766 HILOGI("clientId: %{public}d, result: %{public}d", clientId, result);
767 return GetGattcResult(result);
768 }
769 } // namespace Bluetooth
770 } // namespace OHOS
771 #ifdef __cplusplus
772 }
773 #endif
774 /** @} */