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