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