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 <condition_variable>
17 #include <memory>
18 #include <set>
19
20 #include "bluetooth_errorcode.h"
21 #include "bluetooth_def.h"
22 #include "bluetooth_gatt_client.h"
23 #include "bluetooth_gatt_client_proxy.h"
24 #include "bluetooth_gatt_client_callback_stub.h"
25 #include "bluetooth_host.h"
26 #include "bluetooth_host_proxy.h"
27 #include "bluetooth_log.h"
28 #include "bluetooth_utils.h"
29 #include "gatt_data.h"
30 #include "hilog/log.h"
31 #include "i_bluetooth_gatt_client.h"
32 #include "iservice_registry.h"
33 #include "raw_address.h"
34 #include "system_ability_definition.h"
35
36 namespace OHOS {
37 namespace Bluetooth {
38 constexpr uint8_t REQUEST_TYPE_CHARACTERISTICS_READ = 0x00;
39 constexpr uint8_t REQUEST_TYPE_CHARACTERISTICS_WRITE = 0x01;
40 constexpr uint8_t REQUEST_TYPE_DESCRIPTOR_READ = 0x02;
41 constexpr uint8_t REQUEST_TYPE_DESCRIPTOR_WRITE = 0x03;
42 constexpr uint8_t REQUEST_TYPE_SET_NOTIFY_CHARACTERISTICS = 0x04;
43
44 struct DiscoverInfomation {
45 struct Characteristics {
46 bool isDiscoverDescCompleted_;
CharacteristicsOHOS::Bluetooth::DiscoverInfomation::Characteristics47 Characteristics() : isDiscoverDescCompleted_(false)
48 {}
49 };
50
51 struct Service {
52 bool isDiscoverCompleted_;
53 bool isDiscoverCharacteristicCompleted_;
54 bool isDiscoverIncludeSvcCompleted_;
55 uint16_t endHandle_;
56 std::map<uint16_t, Characteristics> characteristics_;
ServiceOHOS::Bluetooth::DiscoverInfomation::Service57 Service(uint16_t endHandle)
58 : isDiscoverCompleted_(false),
59 isDiscoverCharacteristicCompleted_(false),
60 isDiscoverIncludeSvcCompleted_(false),
61 endHandle_(endHandle)
62 {}
63 };
64 bool isDiscovering_;
65 bool needNotify_;
66 std::mutex mutex_;
67 std::condition_variable condition_;
68 std::map<uint16_t, Service> service_;
DiscoverInfomationOHOS::Bluetooth::DiscoverInfomation69 DiscoverInfomation() : isDiscovering_(false), needNotify_(false)
70 {}
71 };
72
73 struct RequestInformation {
74 bool doing_;
75 uint8_t type_;
76 union {
77 GattCharacteristic *characteristic_;
78 GattDescriptor *descriptor_;
79 } context_;
80 std::mutex mutex_;
RequestInformationOHOS::Bluetooth::RequestInformation81 RequestInformation() : doing_(false)
82 {}
83 };
84
85 struct GattClient::impl {
86 class BluetoothGattClientCallbackStubImpl;
87
88 bool isGetServiceYet_;
89 bool isRegisterSucceeded_;
90 GattClientCallback *callback_;
91 int applicationId_;
92 int connectionState_;
93 BluetoothRemoteDevice device_;
94 sptr<IBluetoothGattClient> proxy_;
95 sptr<BluetoothGattClientCallbackStubImpl> clientCallback_;
96 std::vector<GattService> gattServices_;
97 std::mutex connStateMutex_;
98 RequestInformation requestInformation_;
99 DiscoverInfomation discoverInformation_;
100
101 impl(GattClient &client, const BluetoothRemoteDevice &device);
102 ~impl();
103
104 int DiscoverStart();
105 void DiscoverComplete(int state);
106 void BuildServiceList(const std::vector<BluetoothGattService> &src);
107 GattService *FindService(uint16_t handle);
108 void GetServices();
109 int GetTransport(int &transport);
110 void CleanConnectionInfo();
111 int CheckInterface(void);
112
113 class GattClientDeathRecipient;
114 sptr<GattClientDeathRecipient> deathRecipient_;
115 };
116
117 class GattClient::impl::GattClientDeathRecipient final : public IRemoteObject::DeathRecipient {
118 public:
GattClientDeathRecipient(GattClient::impl & client)119 GattClientDeathRecipient(GattClient::impl &client) : client_(client){};
120 ~GattClientDeathRecipient() final = default;
121 BLUETOOTH_DISALLOW_COPY_AND_ASSIGN(GattClientDeathRecipient);
122
OnRemoteDied(const wptr<IRemoteObject> & remote)123 void OnRemoteDied(const wptr<IRemoteObject> &remote) final
124 {
125 HILOGI("enter");
126 client_.proxy_->AsObject()->RemoveDeathRecipient(client_.deathRecipient_);
127 client_.proxy_ = nullptr;
128 }
129
130 private:
131 GattClient::impl &client_;
132 };
133
134 class GattClient::impl::BluetoothGattClientCallbackStubImpl : public BluetoothGattClientCallbackStub {
135 public:
OnServicesChanged(std::vector<BluetoothGattService> & service)136 void OnServicesChanged(std::vector<BluetoothGattService> &service) override
137 {
138 HILOGI("enter");
139 client_.pimpl->DiscoverStart();
140 }
141
OnConnectionStateChanged(int32_t state,int32_t newState)142 void OnConnectionStateChanged(int32_t state, int32_t newState) override
143 {
144 HILOGI("gattClient conn state, status: %{public}d, newState: %{public}s",
145 state, GetProfileConnStateName(newState).c_str());
146 if (newState == static_cast<int>(BTConnectState::DISCONNECTED)) {
147 client_.pimpl->CleanConnectionInfo();
148 }
149
150 {
151 std::lock_guard<std::mutex> lck(client_.pimpl->connStateMutex_);
152 client_.pimpl->connectionState_ = newState;
153 }
154
155 client_.pimpl->callback_->OnConnectionStateChanged(newState, state);
156 }
157
OnCharacteristicChanged(const BluetoothGattCharacteristic & characteristic)158 void OnCharacteristicChanged(const BluetoothGattCharacteristic &characteristic) override
159 {
160 HILOGI("enter");
161 for (auto &svc : client_.pimpl->gattServices_) {
162 for (auto &character : svc.GetCharacteristics()) {
163 if (character.GetHandle() == characteristic.handle_) {
164 character.SetValue(characteristic.value_.get(), characteristic.length_);
165 client_.pimpl->callback_->OnCharacteristicChanged(character);
166 }
167 }
168 }
169 }
170
OnCharacteristicRead(int32_t ret,const BluetoothGattCharacteristic & characteristic)171 void OnCharacteristicRead(int32_t ret, const BluetoothGattCharacteristic &characteristic) override
172 {
173 HILOGI("enter, ret: %{public}d", ret);
174 std::lock_guard<std::mutex> lock(client_.pimpl->requestInformation_.mutex_);
175 client_.pimpl->requestInformation_.doing_ = false;
176 auto ptr = client_.pimpl->requestInformation_.context_.characteristic_;
177 if (client_.pimpl->requestInformation_.type_ != REQUEST_TYPE_CHARACTERISTICS_READ) {
178 HILOGE("Unexpected call!");
179 }
180 if (GattStatus::GATT_SUCCESS == ret) {
181 ptr->SetValue(characteristic.value_.get(), characteristic.length_);
182 }
183 client_.pimpl->callback_->OnCharacteristicReadResult(*ptr, ret);
184 }
185
OnCharacteristicWrite(int32_t ret,const BluetoothGattCharacteristic & characteristic)186 void OnCharacteristicWrite(int32_t ret, const BluetoothGattCharacteristic &characteristic) override
187 {
188 HILOGI("enter, ret: %{public}d", ret);
189 std::lock_guard<std::mutex> lock(client_.pimpl->requestInformation_.mutex_);
190 client_.pimpl->requestInformation_.doing_ = false;
191 auto ptr = client_.pimpl->requestInformation_.context_.characteristic_;
192 if (client_.pimpl->requestInformation_.type_ != REQUEST_TYPE_CHARACTERISTICS_WRITE) {
193 HILOGE("Unexpected call!");
194 }
195 client_.pimpl->callback_->OnCharacteristicWriteResult(*ptr, ret);
196 }
197
OnDescriptorRead(int32_t ret,const BluetoothGattDescriptor & descriptor)198 void OnDescriptorRead(int32_t ret, const BluetoothGattDescriptor &descriptor) override
199 {
200 HILOGI("enter, ret: %{public}d", ret);
201 std::lock_guard<std::mutex> lock(client_.pimpl->requestInformation_.mutex_);
202 client_.pimpl->requestInformation_.doing_ = false;
203 auto ptr = client_.pimpl->requestInformation_.context_.descriptor_;
204 if (client_.pimpl->requestInformation_.type_ != REQUEST_TYPE_DESCRIPTOR_READ) {
205 HILOGE("Unexpected call!");
206 }
207 if (GattStatus::GATT_SUCCESS == ret) {
208 ptr->SetValue(descriptor.value_.get(), descriptor.length_);
209 }
210 client_.pimpl->callback_->OnDescriptorReadResult(*ptr, ret);
211 }
212
OnDescriptorWrite(int32_t ret,const BluetoothGattDescriptor & descriptor)213 void OnDescriptorWrite(int32_t ret, const BluetoothGattDescriptor &descriptor) override
214 {
215 HILOGI("enter, ret: %{public}d", ret);
216 std::lock_guard<std::mutex> lock(client_.pimpl->requestInformation_.mutex_);
217 client_.pimpl->requestInformation_.doing_ = false;
218 auto ptr = client_.pimpl->requestInformation_.context_.descriptor_;
219 if (client_.pimpl->requestInformation_.type_ == REQUEST_TYPE_DESCRIPTOR_WRITE) {
220 client_.pimpl->callback_->OnDescriptorWriteResult(*ptr, ret);
221 } else if (client_.pimpl->requestInformation_.type_ == REQUEST_TYPE_SET_NOTIFY_CHARACTERISTICS) {
222 client_.pimpl->callback_->OnSetNotifyCharacteristic(ret);
223 } else {
224 HILOGE("Unexpected call!");
225 }
226 }
227
OnMtuChanged(int32_t state,int32_t mtu)228 void OnMtuChanged(int32_t state, int32_t mtu) override
229 {
230 HILOGI("state: %{public}d, mtu: %{public}d", state, mtu);
231 client_.pimpl->callback_->OnMtuUpdate(mtu, state);
232 }
233
OnServicesDiscovered(int32_t status)234 void OnServicesDiscovered(int32_t status) override
235 {
236 HILOGI("status: %{public}d", status);
237 client_.pimpl->DiscoverComplete(status);
238 }
239
OnConnectionParameterChanged(int32_t interval,int32_t latency,int32_t timeout,int32_t status)240 void OnConnectionParameterChanged(int32_t interval, int32_t latency, int32_t timeout, int32_t status) override
241 {
242 HILOGI("interval: %{public}d, latency: %{public}d, timeout: %{public}d, status: %{public}d",
243 interval, latency, timeout, status);
244 client_.pimpl->callback_->OnConnectionParameterChanged(interval, latency, timeout, status);
245 }
246
BluetoothGattClientCallbackStubImpl(GattClient & client)247 BluetoothGattClientCallbackStubImpl(GattClient &client) : client_(client)
248 {}
~BluetoothGattClientCallbackStubImpl()249 ~BluetoothGattClientCallbackStubImpl()
250 {}
251
252 private:
253 GattClient &client_;
254 };
255
impl(GattClient & client,const BluetoothRemoteDevice & device)256 GattClient::impl::impl(GattClient &client, const BluetoothRemoteDevice &device)
257 : isGetServiceYet_(false),
258 isRegisterSucceeded_(false),
259 callback_(nullptr),
260 applicationId_(0),
261 connectionState_(static_cast<int>(BTConnectState::DISCONNECTED)),
262 device_(device)
263 {
264 HILOGI("enter");
265 sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
266 sptr<IRemoteObject> hostRemote = samgr->GetSystemAbility(BLUETOOTH_HOST_SYS_ABILITY_ID);
267
268 if (!hostRemote) {
269 HILOGE("hostRemote is null");
270 return;
271 }
272
273 sptr<IBluetoothHost> hostProxy = iface_cast<IBluetoothHost>(hostRemote);
274 sptr<IRemoteObject> remote = hostProxy->GetProfile(PROFILE_GATT_CLIENT);
275
276 if (!remote) {
277 HILOGE("remote is null");
278 return;
279 }
280 HILOGI("remote obtained");
281 proxy_ = iface_cast<IBluetoothGattClient>(remote);
282 clientCallback_ = new BluetoothGattClientCallbackStubImpl(client);
283
284 deathRecipient_ = new GattClientDeathRecipient(*this);
285 if (!proxy_) {
286 HILOGE("proxy_ is null");
287 } else {
288 proxy_->AsObject()->AddDeathRecipient(deathRecipient_);
289 }
290 }
291
~impl()292 GattClient::impl::~impl()
293 {
294 HILOGI("GattClient ~impl");
295 if (!proxy_) {
296 HILOGE("proxy_ is null");
297 } else {
298 proxy_->AsObject()->RemoveDeathRecipient(deathRecipient_);
299 }
300 }
301
CheckInterface(void)302 int GattClient::impl::CheckInterface(void)
303 {
304 if (proxy_ == nullptr) {
305 HILOGE("proxy_ is nullptr.");
306 return BT_ERR_INTERNAL_ERROR;
307 }
308 if (!BluetoothHost::GetDefaultHost().IsBleEnabled()) {
309 HILOGE("BLE is not enabled.");
310 return BT_ERR_INVALID_STATE;
311 }
312 return BT_SUCCESS;
313 }
314
DiscoverStart()315 int GattClient::impl::DiscoverStart()
316 {
317 {
318 std::unique_lock<std::mutex> lock(discoverInformation_.mutex_);
319 while (discoverInformation_.isDiscovering_) {
320 discoverInformation_.condition_.wait(lock);
321 }
322 discoverInformation_.isDiscovering_ = true;
323 }
324
325 if (!isRegisterSucceeded_) {
326 return BT_ERR_INTERNAL_ERROR;
327 }
328 int result = BT_ERR_INTERNAL_ERROR;
329 if (!proxy_) {
330 HILOGE("proxy_ is null");
331 } else {
332 result = proxy_->DiscoveryServices(applicationId_);
333 if (result != BT_SUCCESS) {
334 DiscoverComplete(BT_ERR_INTERNAL_ERROR);
335 }
336 }
337 return result;
338 }
339
DiscoverComplete(int state)340 void GattClient::impl::DiscoverComplete(int state)
341 {
342 bool ret = false;
343 {
344 std::unique_lock<std::mutex> lock(discoverInformation_.mutex_);
345 if (discoverInformation_.isDiscovering_) {
346 discoverInformation_.isDiscovering_ = false;
347 isGetServiceYet_ = false;
348 discoverInformation_.condition_.notify_all();
349 ret = true;
350 }
351 }
352 if (ret) {
353 callback_->OnServicesDiscovered(state);
354 }
355 }
356
BuildServiceList(const std::vector<BluetoothGattService> & src)357 void GattClient::impl::BuildServiceList(const std::vector<BluetoothGattService> &src)
358 {
359 HILOGI("enter");
360 for (auto &svc : src) {
361 GattService svcTmp(UUID::ConvertFrom128Bits(svc.uuid_.ConvertTo128Bits()),
362 svc.handle_,
363 svc.endHandle_,
364 svc.isPrimary_ ? GattServiceType::PRIMARY : GattServiceType::SECONDARY);
365 for (auto &character : svc.characteristics_) {
366 GattCharacteristic characterTmp(UUID::ConvertFrom128Bits(character.uuid_.ConvertTo128Bits()),
367 character.handle_,
368 character.permissions_,
369 character.properties_);
370 for (auto &desc : character.descriptors_) {
371 characterTmp.AddDescriptor(GattDescriptor(
372 UUID::ConvertFrom128Bits(desc.uuid_.ConvertTo128Bits()), desc.handle_, desc.permissions_));
373 }
374 svcTmp.AddCharacteristic(std::move(characterTmp));
375 }
376 gattServices_.emplace_back(std::move(svcTmp));
377 }
378 for (auto &svc : src) {
379 GattService *ptr = FindService(svc.handle_);
380 if (ptr == NULL) {
381 return;
382 }
383 for (auto &isvc : svc.includeServices_) {
384 GattService *iptr = FindService(isvc.startHandle_);
385 ptr->AddService(*iptr);
386 }
387 }
388 }
389
FindService(uint16_t handle)390 GattService *GattClient::impl::FindService(uint16_t handle)
391 {
392 for (auto &item : gattServices_) {
393 if (item.GetHandle() == handle) {
394 return &item;
395 }
396 }
397 return nullptr;
398 }
399
GetServices()400 void GattClient::impl::GetServices()
401 {
402 HILOGI("enter");
403 std::unique_lock<std::mutex> lock(discoverInformation_.mutex_);
404 while (discoverInformation_.isDiscovering_) {
405 discoverInformation_.condition_.wait(lock);
406 }
407 if (isGetServiceYet_) {
408 HILOGE("isGetServiceYet_ is true");
409 return;
410 }
411 if (!isRegisterSucceeded_) {
412 HILOGE("isRegisterSucceeded_ is false");
413 return;
414 }
415 gattServices_.clear();
416 std::vector<BluetoothGattService> result;
417 if (!proxy_) {
418 HILOGE("proxy_ is null");
419 } else {
420 proxy_->GetServices(applicationId_, result);
421 BuildServiceList(result);
422 isGetServiceYet_ = true;
423 }
424 }
425
GetTransport(int & transport)426 int GattClient::impl::GetTransport(int &transport)
427 {
428 auto deviceType = device_.GetDeviceType();
429 switch (transport) {
430 case GATT_TRANSPORT_TYPE_LE: {
431 if (deviceType == DEVICE_TYPE_BREDR) {
432 return GattStatus::REQUEST_NOT_SUPPORT;
433 }
434 break;
435 }
436 case GATT_TRANSPORT_TYPE_CLASSIC: {
437 if (deviceType == DEVICE_TYPE_LE) {
438 return GattStatus::REQUEST_NOT_SUPPORT;
439 }
440 break;
441 }
442 case GATT_TRANSPORT_TYPE_AUTO: {
443 if (deviceType == DEVICE_TYPE_LE || deviceType == DEVICE_TYPE_DUAL_MONO ||
444 deviceType == DEVICE_TYPE_UNKNOWN) {
445 transport = GATT_TRANSPORT_TYPE_LE;
446 } else {
447 transport = GATT_TRANSPORT_TYPE_CLASSIC;
448 }
449 break;
450 }
451 default:
452 return GattStatus::INVALID_PARAMETER;
453 break;
454 }
455 return GattStatus::GATT_SUCCESS;
456 }
457
CleanConnectionInfo()458 void GattClient::impl::CleanConnectionInfo()
459 {
460 DiscoverComplete(GattStatus::GATT_FAILURE);
461 std::lock_guard<std::mutex> lock(requestInformation_.mutex_);
462 requestInformation_.doing_ = false;
463 }
464
GattClient(const BluetoothRemoteDevice & device)465 GattClient::GattClient(const BluetoothRemoteDevice &device) : pimpl(new GattClient::impl(*this, device))
466 {
467 HILOGI("enter");
468 }
469
~GattClient()470 GattClient::~GattClient()
471 {
472 HILOGI("~GattClient");
473 if (pimpl->isRegisterSucceeded_) {
474 if (!pimpl->proxy_) {
475 HILOGE("proxy_ is null");
476 } else {
477 pimpl->proxy_->DeregisterApplication(pimpl->applicationId_);
478 }
479 }
480 }
481
Connect(GattClientCallback & callback,bool isAutoConnect,int transport)482 int GattClient::Connect(GattClientCallback &callback, bool isAutoConnect, int transport)
483 {
484 HILOGI("enter, isAutoConnect: %{public}d, transport: %{public}d", isAutoConnect, transport);
485 int ret = pimpl->CheckInterface();
486 if (ret != BT_SUCCESS) {
487 return ret;
488 }
489 std::lock_guard<std::mutex> lock(pimpl->connStateMutex_);
490 if (pimpl->connectionState_ == static_cast<int>(BTConnectState::CONNECTED)) {
491 HILOGE("Already connected");
492 return BT_ERR_INTERNAL_ERROR;
493 }
494 HILOGI("isRegisterSucceeded: %{public}d", pimpl->isRegisterSucceeded_);
495 if (pimpl->isRegisterSucceeded_) {
496 return pimpl->proxy_->Connect(pimpl->applicationId_, isAutoConnect);
497 }
498 pimpl->callback_ = &callback;
499 int32_t result = pimpl->GetTransport(transport);
500 if (GattStatus::GATT_SUCCESS != result) {
501 HILOGE("Transport error, status: %{public}d", result);
502 return result;
503 }
504 if ((transport == GATT_TRANSPORT_TYPE_LE && !IS_BLE_ENABLED()) ||
505 (transport == GATT_TRANSPORT_TYPE_CLASSIC && !IS_BT_ENABLED())) {
506 HILOGE("Unsupported mode");
507 return BT_ERR_INTERNAL_ERROR;
508 }
509 if (transport == GATT_TRANSPORT_TYPE_CLASSIC && isAutoConnect) {
510 HILOGE("Unsupported mode");
511 return BT_ERR_INTERNAL_ERROR;
512 }
513 if (!pimpl->device_.IsValidBluetoothRemoteDevice()) {
514 HILOGE("Invalid remote device");
515 return BT_ERR_INTERNAL_ERROR;
516 }
517 int appId = 0;
518 result = pimpl->proxy_->RegisterApplication(
519 pimpl->clientCallback_, bluetooth::RawAddress(pimpl->device_.GetDeviceAddr()), transport, appId);
520 HILOGI("Proxy register application : %{public}d", appId);
521 if (result != BT_SUCCESS) {
522 HILOGE("register application fail");
523 return result;
524 }
525 if (appId > 0) {
526 pimpl->applicationId_ = appId;
527 pimpl->isRegisterSucceeded_ = true;
528 result = pimpl->proxy_->Connect(pimpl->applicationId_, isAutoConnect);
529 }
530 return result;
531 }
532
Disconnect()533 int GattClient::Disconnect()
534 {
535 HILOGI("enter");
536 int ret = pimpl->CheckInterface();
537 if (ret != BT_SUCCESS) {
538 return ret;
539 }
540 std::lock_guard<std::mutex> lock(pimpl->connStateMutex_);
541 if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED) || !pimpl->isRegisterSucceeded_) {
542 HILOGE("Request not supported");
543 return BT_ERR_INTERNAL_ERROR;
544 }
545 int result = BT_ERR_INTERNAL_ERROR;
546 result = pimpl->proxy_->Disconnect(pimpl->applicationId_);
547 return result;
548 }
549
Close()550 int GattClient::Close()
551 {
552 HILOGI("enter");
553 int ret = pimpl->CheckInterface();
554 if (ret != BT_SUCCESS) {
555 return ret;
556 }
557 if (pimpl->isRegisterSucceeded_) {
558 int32_t result = pimpl->proxy_->DeregisterApplication(pimpl->applicationId_);
559 HILOGI("result: %{public}d", result);
560 if (result == BT_SUCCESS) {
561 pimpl->isRegisterSucceeded_ = false;
562 }
563 return result;
564 }
565 HILOGI("isRegisterSucceeded_ is false");
566 return BT_SUCCESS;
567 }
568
DiscoverServices()569 int GattClient::DiscoverServices()
570 {
571 int ret = pimpl->CheckInterface();
572 if (ret != BT_SUCCESS) {
573 return ret;
574 }
575 HILOGI("enter");
576 std::lock_guard<std::mutex> lck(pimpl->connStateMutex_);
577 if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED)) {
578 HILOGE("Request not supported");
579 return BT_ERR_INTERNAL_ERROR;
580 }
581 return pimpl->DiscoverStart();
582 }
583
GetService(const UUID & uuid)584 std::optional<std::reference_wrapper<GattService>> GattClient::GetService(const UUID &uuid)
585 {
586 HILOGI("enter");
587 pimpl->GetServices();
588 for (auto &svc : pimpl->gattServices_) {
589 if (svc.GetUuid().Equals(uuid)) {
590 HILOGI("successful");
591 return svc;
592 }
593 }
594 HILOGE("failed");
595 return std::nullopt;
596 }
597
GetService()598 std::vector<GattService> &GattClient::GetService()
599 {
600 HILOGI("enter");
601 pimpl->GetServices();
602 return pimpl->gattServices_;
603 }
604
ReadCharacteristic(GattCharacteristic & characteristic)605 int GattClient::ReadCharacteristic(GattCharacteristic &characteristic)
606 {
607 HILOGI("enter");
608 int ret = pimpl->CheckInterface();
609 if (ret != BT_SUCCESS) {
610 return ret;
611 }
612 std::lock_guard<std::mutex> lock(pimpl->connStateMutex_);
613 if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED) || !pimpl->isRegisterSucceeded_) {
614 HILOGE("Request not supported");
615 return BT_ERR_INTERNAL_ERROR;
616 }
617 std::lock_guard<std::mutex> lck(pimpl->requestInformation_.mutex_);
618 if (pimpl->requestInformation_.doing_) {
619 HILOGE("Remote device busy");
620 return BT_ERR_INTERNAL_ERROR;
621 }
622 int result = GattStatus::GATT_FAILURE;
623 HILOGI("applicationId: %{public}d, handle: 0x%{public}04X", pimpl->applicationId_, characteristic.GetHandle());
624 result = pimpl->proxy_->ReadCharacteristic(
625 pimpl->applicationId_, (BluetoothGattCharacteristic)bluetooth::Characteristic(characteristic.GetHandle()));
626 HILOGI("result: %{public}d", result);
627 if (result == BT_SUCCESS) {
628 pimpl->requestInformation_.doing_ = true;
629 pimpl->requestInformation_.type_ = REQUEST_TYPE_CHARACTERISTICS_READ;
630 pimpl->requestInformation_.context_.characteristic_ = &characteristic;
631 }
632 return result;
633 }
634
ReadDescriptor(GattDescriptor & descriptor)635 int GattClient::ReadDescriptor(GattDescriptor &descriptor)
636 {
637 HILOGI("enter");
638 int ret = pimpl->CheckInterface();
639 if (ret != BT_SUCCESS) {
640 return ret;
641 }
642 std::lock_guard<std::mutex> lck(pimpl->connStateMutex_);
643 if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED) || !pimpl->isRegisterSucceeded_) {
644 HILOGE("Request not supported");
645 return BT_ERR_INTERNAL_ERROR;
646 }
647 std::lock_guard<std::mutex> lock(pimpl->requestInformation_.mutex_);
648 if (pimpl->requestInformation_.doing_) {
649 HILOGE("Remote device busy");
650 return BT_ERR_INTERNAL_ERROR;
651 }
652 int result = BT_ERR_INTERNAL_ERROR;
653 HILOGI("applicationId: %{public}d, handle: 0x%{public}04X", pimpl->applicationId_, descriptor.GetHandle());
654 result = pimpl->proxy_->ReadDescriptor(
655 pimpl->applicationId_, (BluetoothGattDescriptor)bluetooth::Descriptor(descriptor.GetHandle()));
656 HILOGI("result: %{public}d", result);
657 if (result == BT_SUCCESS) {
658 pimpl->requestInformation_.doing_ = true;
659 pimpl->requestInformation_.type_ = REQUEST_TYPE_DESCRIPTOR_READ;
660 pimpl->requestInformation_.context_.descriptor_ = &descriptor;
661 }
662 return result;
663 }
664
RequestBleMtuSize(int mtu)665 int GattClient::RequestBleMtuSize(int mtu)
666 {
667 HILOGI("enter");
668 int ret = pimpl->CheckInterface();
669 if (ret != BT_SUCCESS) {
670 return ret;
671 }
672 std::lock_guard<std::mutex> lck(pimpl->connStateMutex_);
673 if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED) || !pimpl->isRegisterSucceeded_) {
674 HILOGE("Request not supported");
675 return BT_ERR_INTERNAL_ERROR;
676 }
677 int result = BT_ERR_INTERNAL_ERROR;
678 HILOGI("applicationId: %{public}d, mtu: %{public}d", pimpl->applicationId_, mtu);
679 result = pimpl->proxy_->RequestExchangeMtu(pimpl->applicationId_, mtu);
680 HILOGI("result: %{public}d", result);
681 return result;
682 }
683
SetNotifyCharacteristic(GattCharacteristic & characteristic,bool enable)684 int GattClient::SetNotifyCharacteristic(GattCharacteristic &characteristic, bool enable)
685 {
686 HILOGI("handle: 0x%{public}04X, enable: %{public}d", characteristic.GetHandle(), enable);
687 int ret = pimpl->CheckInterface();
688 if (ret != BT_SUCCESS) {
689 return ret;
690 }
691 static const uint8_t NOTIFICATION[2] = {1, 0};
692 static const uint8_t DEFAULT_VALUE[2] = {0};
693 static const size_t CLIENT_CHARACTERISTIC_CONFIGURATION_VALUE_LENGTH = 0x02;
694 std::lock_guard<std::mutex> lockConn(pimpl->connStateMutex_);
695 if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED)) {
696 HILOGE("Request not supported");
697 return BT_ERR_INTERNAL_ERROR;
698 }
699 auto descriptor = characteristic.GetDescriptor(UUID::FromString("00002902-0000-1000-8000-00805F9B34FB"));
700 if (descriptor == nullptr) {
701 HILOGE("Invalid parameters");
702 return BT_ERR_INTERNAL_ERROR;
703 }
704 std::lock_guard<std::mutex> lock(pimpl->requestInformation_.mutex_);
705 if (pimpl->requestInformation_.doing_) {
706 HILOGI("Remote device busy");
707 return BT_ERR_INTERNAL_ERROR;
708 }
709 BluetoothGattDescriptor desc(bluetooth::Descriptor(descriptor->GetHandle(),
710 (enable ? NOTIFICATION : DEFAULT_VALUE),
711 CLIENT_CHARACTERISTIC_CONFIGURATION_VALUE_LENGTH));
712 int result = GattStatus::GATT_FAILURE;
713 HILOGI("applicationId: %{public}d", pimpl->applicationId_);
714 result = pimpl->proxy_->WriteDescriptor(pimpl->applicationId_, &desc);
715 HILOGI("result: %{public}d", result);
716 if (result == BT_SUCCESS) {
717 pimpl->requestInformation_.type_ = REQUEST_TYPE_SET_NOTIFY_CHARACTERISTICS;
718 pimpl->requestInformation_.context_.descriptor_ = descriptor;
719 pimpl->requestInformation_.doing_ = true;
720 }
721 return result;
722 }
723
WriteCharacteristic(GattCharacteristic & characteristic)724 int GattClient::WriteCharacteristic(GattCharacteristic &characteristic)
725 {
726 HILOGI("enter");
727 int ret = pimpl->CheckInterface();
728 if (ret != BT_SUCCESS) {
729 return ret;
730 }
731 std::lock_guard<std::mutex> lockConn(pimpl->connStateMutex_);
732 if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED)) {
733 HILOGE("Request not supported");
734 return BT_ERR_INTERNAL_ERROR;
735 }
736 size_t length = 0;
737 auto &characterValue = characteristic.GetValue(&length);
738 HILOGI("length:%{public}zu", length);
739 if (characterValue == nullptr || length == 0) {
740 HILOGE("Invalid parameters");
741 return BT_ERR_INTERNAL_ERROR;
742 }
743 std::lock_guard<std::mutex> lock(pimpl->requestInformation_.mutex_);
744 if (pimpl->requestInformation_.doing_) {
745 HILOGE("Remote device busy");
746 return BT_ERR_INTERNAL_ERROR;
747 }
748 BluetoothGattCharacteristic character(
749 bluetooth::Characteristic(characteristic.GetHandle(), characterValue.get(), length));
750 int result = BT_ERR_INTERNAL_ERROR;
751 bool withoutRespond = true;
752 if (characteristic.GetWriteType() == static_cast<int>(GattCharacteristic::WriteType::SIGNED)) {
753 HILOGI("Signed write");
754 result = pimpl->proxy_->SignedWriteCharacteristic(pimpl->applicationId_, &character);
755 } else {
756 withoutRespond = ((characteristic.GetWriteType() ==
757 static_cast<int>(GattCharacteristic::WriteType::DEFAULT)) ? false : true);
758 HILOGI("Write without response");
759 result = pimpl->proxy_->WriteCharacteristic(pimpl->applicationId_, &character, withoutRespond);
760 }
761 if (result && !withoutRespond == GattStatus::GATT_SUCCESS) {
762 HILOGI("successful");
763 pimpl->requestInformation_.type_ = REQUEST_TYPE_CHARACTERISTICS_WRITE;
764 pimpl->requestInformation_.context_.characteristic_ = &characteristic;
765 pimpl->requestInformation_.doing_ = true;
766 } else {
767 HILOGI("result: %{public}d", result);
768 }
769 return result;
770 }
771
WriteDescriptor(GattDescriptor & descriptor)772 int GattClient::WriteDescriptor(GattDescriptor &descriptor)
773 {
774 HILOGI("enter");
775 int ret = pimpl->CheckInterface();
776 if (ret != BT_SUCCESS) {
777 return ret;
778 }
779 std::lock_guard<std::mutex> lck(pimpl->connStateMutex_);
780 if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED) || !pimpl->isRegisterSucceeded_) {
781 HILOGE("Request not supported");
782 return BT_ERR_INTERNAL_ERROR;
783 }
784 size_t length = 0;
785 auto &characterValue = descriptor.GetValue(&length);
786 if (characterValue == nullptr || length == 0) {
787 HILOGE("Invalid parameters");
788 return BT_ERR_INTERNAL_ERROR;
789 }
790 std::lock_guard<std::mutex> lock(pimpl->requestInformation_.mutex_);
791 if (pimpl->requestInformation_.doing_) {
792 HILOGE("Remote device busy");
793 return BT_ERR_INTERNAL_ERROR;
794 }
795 int result = BT_ERR_INTERNAL_ERROR;
796 BluetoothGattDescriptor desc(bluetooth::Descriptor(descriptor.GetHandle(), characterValue.get(), length));
797 result = pimpl->proxy_->WriteDescriptor(pimpl->applicationId_, &desc);
798 HILOGI("result: %{public}d", result);
799 if (result == BT_SUCCESS) {
800 pimpl->requestInformation_.doing_ = true;
801 pimpl->requestInformation_.type_ = REQUEST_TYPE_DESCRIPTOR_WRITE;
802 pimpl->requestInformation_.context_.descriptor_ = &descriptor;
803 }
804 return result;
805 }
806
RequestConnectionPriority(int connPriority)807 int GattClient::RequestConnectionPriority(int connPriority)
808 {
809 int ret = pimpl->CheckInterface();
810 if (ret != BT_SUCCESS) {
811 return ret;
812 }
813 std::lock_guard<std::mutex> lockConn(pimpl->connStateMutex_);
814 if (pimpl->connectionState_ != static_cast<int>(BTConnectState::CONNECTED)) {
815 HILOGE("Not connected");
816 return GattStatus::REQUEST_NOT_SUPPORT;
817 }
818 if (connPriority != static_cast<int>(GattConnectionPriority::BALANCED) &&
819 connPriority != static_cast<int>(GattConnectionPriority::HIGH) &&
820 connPriority != static_cast<int>(GattConnectionPriority::LOW_POWER)) {
821 HILOGE("Invalid parameters");
822 return GattStatus::INVALID_PARAMETER;
823 }
824 int result = GattStatus::GATT_FAILURE;
825 result = pimpl->proxy_->RequestConnectionPriority(pimpl->applicationId_, connPriority);
826 HILOGI("result: %{public}d", result);
827 return result;
828 }
829 } // namespace Bluetooth
830 } // namespace OHOS