1 /*
2 * Copyright (C) 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 "hid_host_hogp.h"
17 #include "hid_host_service.h"
18
19 namespace OHOS {
20 namespace bluetooth {
HidHostHogp(const std::string & address)21 HidHostHogp::HidHostHogp(const std::string &address) : address_(address)
22 {
23 gattCallback_ = std::make_unique<HogpGattClientCallback>(this);
24 state_ = HID_HOST_HOGP_STATE_UNUSED;
25 appId_ = RegisterGattClientApplication(RawAddress(address_));
26 LOG_DEBUG("[HOGP] %{public}s: appId_ %{public}d ", __func__, appId_);
27 dispatcher_ = std::make_unique<Dispatcher>(address_);
28 }
29
~HidHostHogp()30 HidHostHogp::~HidHostHogp()
31 {
32 DeregisterGattClientApplication();
33 dispatcher_->Uninitialize();
34 dispatcher_ = nullptr;
35 }
36
RegisterGattClientApplication(const RawAddress & addr)37 int HidHostHogp::RegisterGattClientApplication(const RawAddress &addr)
38 {
39 IProfileGattClient *gattClientService_ = GetGattClientService();
40 if (gattClientService_ != nullptr) {
41 return gattClientService_->RegisterSharedApplication(
42 *gattCallback_, addr, BTTransport::ADAPTER_BLE);
43 }
44 LOG_ERROR("[Hogp] %{public}s: gattClientService is null. return ", __func__);
45 return RET_BAD_STATUS;
46 }
47
DeregisterGattClientApplication()48 int HidHostHogp::DeregisterGattClientApplication()
49 {
50 IProfileGattClient *gattClientService_ = GetGattClientService();
51 int ret = RET_BAD_STATUS;
52 if (gattClientService_ != nullptr) {
53 ret = gattClientService_->DeregisterApplication(appId_);
54 if (ret == BT_SUCCESS) {
55 appId_ = -1;
56 }
57 LOG_DEBUG("[HOGP] %{public}s: DeregisterApplication return %{public}d", __func__, ret);
58 } else {
59 LOG_ERROR("[Hogp] %{public}s: gattClientService is null.", __func__);
60 }
61
62 return ret;
63 }
64
Connect()65 int HidHostHogp::Connect()
66 {
67 LOG_DEBUG("[HOGP] %{public}s: appId_ %{public}d", __func__, appId_);
68 if (appId_ < 0) {
69 LOG_ERROR("[HOGP] %{public}s:appId_ is error appId_ = %{public}d", __func__, appId_);
70 return RET_BAD_STATUS;
71 }
72 IProfileGattClient *gattClientService_ = GetGattClientService();
73 if (gattClientService_ == nullptr) {
74 LOG_ERROR("[HOGP] %{public}s:gattClientService is null.", __func__);
75 return RET_BAD_STATUS;
76 }
77 if (state_ == HID_HOST_HOGP_STATE_CONNECTED) {
78 LOG_DEBUG("[HOGP] %{public}s: HOGP is connected state", __func__);
79 HidHostMessage event(HID_HOST_OPEN_CMPL_EVT);
80 event.dev_ = address_;
81 HidHostService::GetService()->PostEvent(event);
82 return BT_SUCCESS;
83 }
84 if (state_ != HID_HOST_HOGP_STATE_UNUSED) {
85 LOG_ERROR("[HOGP] %{public}s:state error state = %{public}d", __func__, state_);
86 return RET_BAD_STATUS;
87 }
88
89 int ret = gattClientService_->Connect(appId_, false);
90 if (ret != BT_SUCCESS) {
91 LOG_ERROR("[HOGP] %{public}s:gatt connect faild ret = %{public}d", __func__, ret);
92 return ret;
93 }
94 state_ = HID_HOST_HOGP_STATE_CONNECTING;
95 return ret;
96 }
97
Disconnect()98 int HidHostHogp::Disconnect()
99 {
100 if (appId_ < 0) {
101 LOG_ERROR("[HOGP] %{public}s:appId_ is error appId_ = %{public}d", __func__, appId_);
102 return RET_BAD_STATUS;
103 }
104 if (state_ == HID_HOST_CONN_STATE_UNUSED) {
105 LOG_DEBUG("[HOGP] %{public}s: HOGP is disconnected state", __func__);
106 HidHostMessage event(HID_HOST_INT_CLOSE_EVT);
107 event.dev_ = address_;
108 HidHostService::GetService()->PostEvent(event);
109 return BT_SUCCESS;
110 }
111 IProfileGattClient *gattClientService_ = GetGattClientService();
112 if (gattClientService_ == nullptr) {
113 LOG_ERROR("[HOGP] %{public}s:gattClientService is null.", __func__);
114 return RET_BAD_STATUS;
115 }
116 int ret = gattClientService_->Disconnect(appId_);
117 if (ret != BT_SUCCESS) {
118 LOG_ERROR("[HOGP] %{public}s:gatt disconnect faild ret = %{public}d", __func__, ret);
119 return ret;
120 }
121 state_ = HID_HOST_HOGP_STATE_DISCONNECTING;
122 return ret;
123 }
124
SendData(const HidHostMessage & msg)125 int HidHostHogp::SendData(const HidHostMessage &msg)
126 {
127 dispatcher_->Initialize();
128 dispatcher_->PostTask(std::bind(&HidHostHogp::SendData_, this, msg));
129 return BT_SUCCESS;
130 }
131
SendData_(const HidHostMessage & msg)132 void HidHostHogp::SendData_(const HidHostMessage &msg)
133 {
134 HogpReport* report = FindReportByTypeAndId(msg.sendData_.param, msg.sendData_.reportId);
135 if (report == nullptr) {
136 LOG_ERROR("[HOGP] %{public}s:not find report", __func__);
137 } else if (report->character == nullptr) {
138 LOG_ERROR("[HOGP] %{public}s:report character is null", __func__);
139 } else {
140 switch (msg.sendData_.type) {
141 case HID_HOST_DATA_TYPE_GET_REPORT:
142 SendGetReport(report->reportId, *report->character);
143 break;
144 case HID_HOST_DATA_TYPE_SET_REPORT:
145 SendSetReport(*report->character, msg.dataLength_, msg.data_.get());
146 break;
147 default:
148 break;
149 }
150 }
151 SendStopHogpThread();
152 }
153
SendStopHogpThread()154 void HidHostHogp::SendStopHogpThread()
155 {
156 HidHostMessage event(HID_HOST_HOGP_STOP_THREAD_EVT);
157 event.dev_ = address_;
158 HidHostService::GetService()->PostEvent(event);
159 }
160
SendGetReport(uint8_t reportId,Characteristic character)161 int HidHostHogp::SendGetReport(uint8_t reportId, Characteristic character)
162 {
163 IProfileGattClient *gattClientService = GetGattClientService();
164 if (gattClientService == nullptr) {
165 ReceiveHandShake(HID_HOST_HANDSHAKE_ERROR);
166 LOG_ERROR("[HOGP] %{public}s:gattClientService is null.", __func__);
167 return RET_BAD_STATUS;
168 }
169 std::unique_lock<std::mutex> lock(mutexWaitGattCallback_);
170 gattClientService->ReadCharacteristic(appId_, character);
171 if (cvfull_.wait_for(lock,
172 std::chrono::seconds(HOGP_GATT_THREAD_WAIT_TIMEOUT)) == std::cv_status::timeout) {
173 LOG_ERROR("[HOGP] %{public}s:get report timeout", __func__);
174 ReceiveHandShake(HID_HOST_HANDSHAKE_ERROR);
175 return RET_BAD_STATUS;
176 }
177 if ((characteristicTemp_ != nullptr) &&
178 (character.handle_ == characteristicTemp_->handle_)) {
179 int ret = ReceiveControlData(*characteristicTemp_, reportId);
180 characteristicTemp_ = nullptr;
181 return ret;
182 }
183 LOG_ERROR("[HOGP] %{public}s:handle_ is error", __func__);
184 ReceiveHandShake(HID_HOST_HANDSHAKE_ERROR);
185 return RET_BAD_STATUS;
186 }
187
SendSetReport(Characteristic character,int length,uint8_t * pkt)188 int HidHostHogp::SendSetReport(Characteristic character, int length, uint8_t* pkt)
189 {
190 IProfileGattClient *gattClientService = GetGattClientService();
191 if (gattClientService == nullptr) {
192 LOG_ERROR("[HOGP] %{public}s:gattClientService is null.", __func__);
193 ReceiveHandShake(HID_HOST_HANDSHAKE_ERROR);
194 return RET_BAD_STATUS;
195 }
196 if (length <= 1) {
197 LOG_ERROR("[HOGP] %{public}s:data length is error", __func__);
198 ReceiveHandShake(HID_HOST_HANDSHAKE_ERROR);
199 return RET_BAD_STATUS;
200 }
201 std::unique_lock<std::mutex> lock(mutexWaitGattCallback_);
202 // Delete report id from the data
203 character.length_ = static_cast<size_t>(length - 1);
204 character.value_ = std::make_unique<uint8_t[]>(character.length_);
205 if (memcpy_s(character.value_.get(), length - 1, pkt + 1, length - 1) != EOK) {
206 LOG_ERROR("[HOGP] %{public}s:character copy error", __func__);
207 ReceiveHandShake(HID_HOST_HANDSHAKE_ERROR);
208 return RET_BAD_STATUS;
209 }
210 gattClientService->WriteCharacteristic(appId_, character);
211 if (cvfull_.wait_for(lock,
212 std::chrono::seconds(HOGP_GATT_THREAD_WAIT_TIMEOUT)) == std::cv_status::timeout) {
213 LOG_ERROR("[HOGP] %{public}s:set report timeout", __func__);
214 ReceiveHandShake(HID_HOST_HANDSHAKE_ERROR);
215 return RET_BAD_STATUS;
216 }
217 if ((characteristicTemp_ != nullptr) &&
218 (character.handle_ == characteristicTemp_->handle_)) {
219 ReceiveHandShake(HID_HOST_SUCCESS);
220 characteristicTemp_ = nullptr;
221 return BT_SUCCESS;
222 }
223 LOG_ERROR("[HOGP] %{public}s:handle_ is error", __func__);
224 ReceiveHandShake(HID_HOST_HANDSHAKE_ERROR);
225 return RET_BAD_STATUS;
226 }
227
ReceiveHandShake(uint16_t err)228 void HidHostHogp::ReceiveHandShake(uint16_t err)
229 {
230 HidHostMessage event(HID_HOST_INT_HANDSK_EVT, err);
231 event.dev_ = address_;
232 HidHostService::GetService()->PostEvent(event);
233 }
234
ReceiveControlData(Characteristic character,uint8_t reportId)235 int HidHostHogp::ReceiveControlData(Characteristic character, uint8_t reportId)
236 {
237 if ((character.value_ != nullptr) && (character.length_ != 0)) {
238 HidHostMessage event(HID_HOST_INT_CTRL_DATA);
239 event.dev_ = address_;
240 // Add report id as the first byte of the report before sending it to uhid
241 event.dataLength_ = static_cast<int>(character.length_ + 1);
242 event.data_ = std::make_unique<uint8_t[]>(event.dataLength_);
243 event.data_[0] = reportId;
244 if (memcpy_s(event.data_.get() + 1, character.length_,
245 character.value_.get(), character.length_) != EOK) {
246 LOG_ERROR("[HOGP]%{public}s():memcpy error", __FUNCTION__);
247 return RET_BAD_STATUS;
248 }
249 HidHostService::GetService()->PostEvent(event);
250 return BT_SUCCESS;
251 } else {
252 LOG_ERROR("[HOGP]%{public}s():data is null length_=%{public}zu", __FUNCTION__, character.length_);
253 ReceiveHandShake(HID_HOST_HANDSHAKE_ERROR);
254 }
255 return RET_BAD_STATUS;
256 }
257
FindReportByTypeAndId(uint8_t type,uint8_t reportId)258 HogpReport* HidHostHogp::FindReportByTypeAndId(uint8_t type, uint8_t reportId)
259 {
260 for (auto iter = reports_.begin(); iter != reports_.end(); ++iter) {
261 if ((iter->second != nullptr) && (iter->second->reportId == reportId) &&
262 (iter->second->reportType == type)) {
263 return iter->second.get();
264 }
265 }
266 return nullptr;
267 }
268
GetRemotePnpInfo()269 PnpInformation& HidHostHogp::GetRemotePnpInfo()
270 {
271 return pnpInf_;
272 }
273
GetRemoteHidInfo()274 HidInformation& HidHostHogp::GetRemoteHidInfo()
275 {
276 return hidInf_;
277 }
278
GetGattClientService()279 IProfileGattClient *HidHostHogp::GetGattClientService()
280 {
281 return static_cast<IProfileGattClient *>(IProfileManager::GetInstance()
282 ->GetProfileService(PROFILE_NAME_GATT_CLIENT));
283 }
284
DiscoverStart()285 int HidHostHogp::DiscoverStart()
286 {
287 LOG_DEBUG("[HOGP]%{public}s", __FUNCTION__);
288 int result;
289 IProfileGattClient *gattClientService = GetGattClientService();
290 if (gattClientService == nullptr) {
291 LOG_ERROR("[HOGP] %{public}s:gattClientService is null.", __func__);
292 return RET_BAD_STATUS;
293 }
294 result = gattClientService->DiscoveryServices(appId_);
295 if (result != BT_SUCCESS) {
296 LOG_ERROR("[HOGP] %{public}s:DiscoveryServices faild result=%{public}d", __func__, result);
297 Disconnect();
298 } else {
299 state_ = HID_HOST_HOGP_STATE_DISCOVERING;
300 }
301 return result;
302 }
303
OnConnectionStateChangedTask(int newState)304 void HidHostHogp::OnConnectionStateChangedTask(int newState)
305 {
306 LOG_DEBUG("[HOGP]%{public}s state:%{public}d", __FUNCTION__, newState);
307 if (newState == static_cast<int>(BTConnectState::CONNECTED)) {
308 DiscoverStart();
309 } else if (newState == static_cast<int>(BTConnectState::DISCONNECTED)) {
310 state_ = HID_HOST_HOGP_STATE_UNUSED;
311
312 HidHostMessage event(HID_HOST_INT_CLOSE_EVT);
313 event.dev_ = address_;
314 HidHostService::GetService()->PostEvent(event);
315 }
316 }
317
OnServicesDiscoveredTask(int status)318 void HidHostHogp::OnServicesDiscoveredTask(int status)
319 {
320 OnServicesDiscoveredTask_(status);
321 SendStopHogpThread();
322 }
323
OnServicesDiscoveredTask_(int status)324 void HidHostHogp::OnServicesDiscoveredTask_(int status)
325 {
326 LOG_DEBUG("[HOGP]%{public}s state:%{public}d", __FUNCTION__, status);
327 if (state_ == HID_HOST_HOGP_STATE_DISCOVERING) {
328 if (status != GattStatus::GATT_SUCCESS) {
329 LOG_ERROR("[HOGP] %{public}s:discover failed status=%{public}d", __func__, status);
330 Disconnect();
331 return;
332 }
333 IProfileGattClient *gattClientService = GetGattClientService();
334 if (gattClientService == nullptr) {
335 LOG_ERROR("[HOGP] %{public}s:gattClientService is null.", __func__);
336 return;
337 }
338 std::vector<Service> services = gattClientService->GetServices(appId_);
339 int ret = BT_SUCCESS;
340 for (auto &service : services) {
341 if (service.uuid_ == Uuid::ConvertFrom16Bits(UUID_DEVICE_INFORMATION_SERVICE)) {
342 ret = GetPnpInformation(service);
343 } else if (service.uuid_ == Uuid::ConvertFrom16Bits(HID_HOST_UUID_SERVCLASS_LE_HID)) {
344 ret = GetHidInformation(service);
345 } else if (service.uuid_ == Uuid::ConvertFrom16Bits(HID_HOST_UUID_BATTERY_SERVICE)) {
346 LOG_INFO("[HOGP] %{public}s:for pts to get battery level.", __func__);
347 GetBatteryInformation(service);
348 }
349 if (ret != BT_SUCCESS) {
350 Disconnect();
351 return;
352 }
353 }
354 SetInputReportNotification();
355 state_ = HID_HOST_HOGP_STATE_CONNECTED;
356 HidHostMessage event(HID_HOST_OPEN_CMPL_EVT);
357 event.dev_ = address_;
358 HidHostService::GetService()->PostEvent(event);
359 }
360 }
361
GetPnpInformation(Service service)362 int HidHostHogp::GetPnpInformation(Service service)
363 {
364 IProfileGattClient *gattClientService = GetGattClientService();
365 if (gattClientService == nullptr) {
366 LOG_ERROR("[HOGP] %{public}s:gattClientService is null.", __func__);
367 return RET_BAD_STATUS;
368 }
369 for (auto &character : service.characteristics_) {
370 if (character.uuid_ == Uuid::ConvertFrom16Bits(HID_HOST_UUID_GATT_PNP_ID)) {
371 std::unique_lock<std::mutex> lock(mutexWaitGattCallback_);
372 gattClientService->ReadCharacteristic(appId_, character);
373 if (cvfull_.wait_for(lock,
374 std::chrono::seconds(HOGP_GATT_THREAD_WAIT_TIMEOUT)) == std::cv_status::timeout) {
375 LOG_ERROR("[HOGP] %{public}s:GetPnpInformation timeout", __func__);
376 return RET_BAD_STATUS;
377 }
378 if ((characteristicTemp_ != nullptr) &&
379 (character.handle_ == characteristicTemp_->handle_)) {
380 int ret = SavePnpInformation(*characteristicTemp_);
381 characteristicTemp_ = nullptr;
382 return ret;
383 }
384 LOG_ERROR("[HOGP] %{public}s:handle_ is error", __func__);
385 return RET_BAD_STATUS;
386 }
387 }
388 return RET_BAD_STATUS;
389 }
390
GetHidInformation(Service service)391 int HidHostHogp::GetHidInformation(Service service)
392 {
393 IProfileGattClient *gattClientService = GetGattClientService();
394 if (gattClientService == nullptr) {
395 LOG_ERROR("[HOGP] %{public}s:gattClientService is null.", __func__);
396 return RET_BAD_STATUS;
397 }
398 for (auto &character : service.characteristics_) {
399 int ret = BT_SUCCESS;
400 if (character.uuid_ == Uuid::ConvertFrom16Bits(HID_HOST_UUID_GATT_HID_INFORMATION)) {
401 std::unique_lock<std::mutex> lock(mutexWaitGattCallback_);
402 gattClientService->ReadCharacteristic(appId_, character);
403 if (cvfull_.wait_for(lock,
404 std::chrono::seconds(HOGP_GATT_THREAD_WAIT_TIMEOUT)) == std::cv_status::timeout) {
405 LOG_ERROR("[HOGP] %{public}s:GetHidInformation timeout", __func__);
406 return RET_BAD_STATUS;
407 }
408 if ((characteristicTemp_ != nullptr) &&
409 (character.handle_ == characteristicTemp_->handle_)) {
410 ret = SaveHidInformation(*characteristicTemp_);
411 characteristicTemp_ = nullptr;
412 } else {
413 LOG_ERROR("[HOGP] %{public}s:handle_ is error", __func__);
414 return RET_BAD_STATUS;
415 }
416 } else if (character.uuid_ == Uuid::ConvertFrom16Bits(HID_HOST_UUID_GATT_HID_REPORT_MAP)) {
417 ret = GetHidReportMap(character);
418 } else if (character.uuid_ == Uuid::ConvertFrom16Bits(HID_HOST_UUID_GATT_HID_REPORT)) {
419 GetHidReport(character);
420 GetExternalCfgInfo(character);
421 }
422 if (ret != BT_SUCCESS) {
423 return ret;
424 }
425 }
426 return BT_SUCCESS;
427 }
428
GetBatteryInformation(Service service)429 void HidHostHogp::GetBatteryInformation(Service service)
430 {
431 IProfileGattClient *gattClientService = GetGattClientService();
432 if (gattClientService == nullptr) {
433 LOG_ERROR("[HOGP] %{public}s:gattClientService is null.", __func__);
434 return;
435 }
436
437 for (auto &character : service.characteristics_) {
438 if (character.uuid_ == Uuid::ConvertFrom16Bits(HID_HOST_UUID_GATT_BATTERY_LEVEL)) {
439 std::unique_lock<std::mutex> lock(mutexWaitGattCallback_);
440 gattClientService->ReadCharacteristic(appId_, character);
441 if (cvfull_.wait_for(lock,
442 std::chrono::seconds(HOGP_GATT_THREAD_WAIT_TIMEOUT)) == std::cv_status::timeout) {
443 LOG_ERROR("[HOGP] %{public}s: GetBatteryInformation timeout", __func__);
444 return;
445 }
446 }
447 }
448 }
449
GetHidReportMap(Characteristic character)450 int HidHostHogp::GetHidReportMap(Characteristic character)
451 {
452 IProfileGattClient *gattClientService = GetGattClientService();
453 if (gattClientService == nullptr) {
454 LOG_ERROR("[HOGP] %{public}s:gattClientService is null.", __func__);
455 return RET_BAD_STATUS;
456 }
457 {
458 std::unique_lock<std::mutex> lock(mutexWaitGattCallback_);
459 gattClientService->ReadCharacteristic(appId_, character);
460 if (cvfull_.wait_for(lock,
461 std::chrono::seconds(HOGP_GATT_THREAD_WAIT_TIMEOUT)) == std::cv_status::timeout) {
462 LOG_ERROR("[HOGP] %{public}s:GetHidReportMap timeout", __func__);
463 return RET_BAD_STATUS;
464 }
465 }
466
467 GetExternalRptRefInfo(character);
468
469 if ((characteristicTemp_ != nullptr) &&
470 (character.handle_ == characteristicTemp_->handle_)) {
471 int ret = SaveReportMap(*characteristicTemp_);
472 characteristicTemp_ = nullptr;
473 return ret;
474 }
475 LOG_ERROR("[HOGP] %{public}s:handle_ is error", __func__);
476 return RET_BAD_STATUS;
477 }
478
GetExternalRptRefInfo(Characteristic character)479 void HidHostHogp::GetExternalRptRefInfo(Characteristic character)
480 {
481 IProfileGattClient *gattClientService = GetGattClientService();
482 if (gattClientService == nullptr) {
483 LOG_ERROR("[HOGP] %{public}s:gattClientService is null.", __func__);
484 return;
485 }
486
487 for (auto &descriptor : character.descriptors_) {
488 if (descriptor.uuid_ == Uuid::ConvertFrom16Bits(HID_HOST_UUID_GATT_EXT_RPT_REF)) {
489 LOG_INFO("[HOGP] %{public}s:for pts to get external report reference.", __func__);
490 std::unique_lock<std::mutex> lock(mutexWaitGattCallback_);
491 gattClientService->ReadDescriptor(appId_, descriptor);
492 if (cvfull_.wait_for(lock,
493 std::chrono::seconds(HOGP_GATT_THREAD_WAIT_TIMEOUT)) == std::cv_status::timeout) {
494 LOG_ERROR("[HOGP] %{public}s:GetExternalRptRefInfo timeout", __func__);
495 return;
496 }
497 }
498 }
499 }
500
GetExternalCfgInfo(Characteristic character)501 void HidHostHogp::GetExternalCfgInfo(Characteristic character)
502 {
503 IProfileGattClient *gattClientService = GetGattClientService();
504 if (gattClientService == nullptr) {
505 LOG_ERROR("[HOGP] %{public}s:gattClientService is null.", __func__);
506 return;
507 }
508
509 for (auto &descriptor : character.descriptors_) {
510 if (descriptor.uuid_ == Uuid::ConvertFrom16Bits(HID_HOST_UUID_GATT_EXT_CFG_REF)) {
511 LOG_INFO("[HOGP] %{public}s:for pts to get external report reference.", __func__);
512 std::unique_lock<std::mutex> lock(mutexWaitGattCallback_);
513 gattClientService->ReadDescriptor(appId_, descriptor);
514 if (cvfull_.wait_for(lock,
515 std::chrono::seconds(HOGP_GATT_THREAD_WAIT_TIMEOUT)) == std::cv_status::timeout) {
516 LOG_ERROR("[HOGP] %{public}s:GetExternalRptRefInfo timeout", __func__);
517 return;
518 }
519 } else {
520 LOG_ERROR("[HOGP] %{public}s:NOT FOUND", __func__);
521 }
522 }
523 }
524
GetHidReport(Characteristic character)525 void HidHostHogp::GetHidReport(Characteristic character)
526 {
527 IProfileGattClient *gattClientService = GetGattClientService();
528 if (gattClientService == nullptr) {
529 LOG_ERROR("[HOGP] %{public}s:gattClientService is null.", __func__);
530 return;
531 }
532 Descriptor confifDefault;
533 std::unique_ptr<Descriptor> config = std::make_unique<Descriptor>(confifDefault);
534 std::unique_ptr<Descriptor> reference = nullptr;
535 for (auto &descriptor : character.descriptors_) {
536 if (descriptor.uuid_ == Uuid::ConvertFrom16Bits(HID_HOST_UUID_GATT_REPORT_REFERENCE)) {
537 reference = std::make_unique<Descriptor>(descriptor);
538 } else if (descriptor.uuid_ == Uuid::ConvertFrom16Bits(HID_HOST_UUID_GATT_CLIENT_CHAR_CONFIG)) {
539 config = std::make_unique<Descriptor>(descriptor);
540 }
541 }
542
543 if ((config == nullptr) || (reference == nullptr)) {
544 LOG_ERROR("[HOGP] %{public}s:not find config or reference", __func__);
545 return;
546 }
547
548 std::unique_lock<std::mutex> lock(mutexWaitGattCallback_);
549 gattClientService->ReadDescriptor(appId_, *reference);
550 if (cvfull_.wait_for(lock,
551 std::chrono::seconds(HOGP_GATT_THREAD_WAIT_TIMEOUT)) == std::cv_status::timeout) {
552 LOG_ERROR("[HOGP] %{public}s:GetHidReport timeout", __func__);
553 return;
554 }
555
556 if (descriptorTemp_ != nullptr) {
557 SaveReport(character, *descriptorTemp_, *config);
558 descriptorTemp_ = nullptr;
559 } else {
560 LOG_ERROR("[HOGP] %{public}s:handle_ is error", __func__);
561 }
562 }
563
SavePnpInformation(Characteristic character)564 int HidHostHogp::SavePnpInformation(Characteristic character)
565 {
566 if (character.length_ != HID_HOST_PNP_ID_SIZE) {
567 LOG_ERROR("[HOGP] %{public}s:character length_ is error length=%{public}zu",
568 __func__, character.length_);
569 return RET_BAD_STATUS;
570 }
571 uint8_t *data = character.value_.get();
572 int offset = 1;
573 pnpInf_.vendorId = static_cast<uint16_t>(data[offset]) +
574 static_cast<uint16_t>(static_cast<uint16_t>(data[offset + 1]) << HID_HOST_SHIFT_OPRATURN_8);
575 offset += sizeof(uint16_t);
576 pnpInf_.productId = static_cast<uint16_t>(data[offset]) +
577 static_cast<uint16_t>(static_cast<uint16_t>(data[offset + 1]) << HID_HOST_SHIFT_OPRATURN_8);
578 offset += sizeof(uint16_t);
579 pnpInf_.version = static_cast<uint16_t>(data[offset]) +
580 static_cast<uint16_t>(static_cast<uint16_t>(data[offset + 1]) << HID_HOST_SHIFT_OPRATURN_8);
581 LOG_DEBUG(
582 "[HOGP]%{public}s():vendorId = 0x%{public}x,productId = 0x%{public}x,version = 0x%{public}x",
583 __FUNCTION__, pnpInf_.vendorId, pnpInf_.productId, pnpInf_.version);
584 return BT_SUCCESS;
585 }
586
SaveHidInformation(Characteristic character)587 int HidHostHogp::SaveHidInformation(Characteristic character)
588 {
589 if (character.length_ != HID_HOST_HID_INFORMATION_SIZE) {
590 LOG_ERROR("[HOGP] %{public}s:character length_ is error length=%{public}zu",
591 __func__, character.length_);
592 return RET_BAD_STATUS;
593 }
594 hidInf_.ctryCode = *(character.value_.get() + HID_HOST_CTRY_CODE_OFFSET);
595 LOG_DEBUG("[HOGP]%{public}s():ctryCode = 0x%{public}x", __FUNCTION__, hidInf_.ctryCode);
596 return BT_SUCCESS;
597 }
598
SaveReportMap(Characteristic character)599 int HidHostHogp::SaveReportMap(Characteristic character)
600 {
601 if (character.length_ <= 0) {
602 LOG_ERROR("[HOGP] %{public}s:character length_ is error length=%{public}zu",
603 __func__, character.length_);
604 return RET_BAD_STATUS;
605 }
606 hidInf_.descInfo = std::make_unique<uint8_t[]>(character.length_);
607 if (memcpy_s(hidInf_.descInfo.get(), character.length_, character.value_.get(), character.length_) != EOK) {
608 hidInf_.descInfo = nullptr;
609 hidInf_.descLength = 0;
610 LOG_ERROR("[HOGP] %{public}s:info copy is error", __func__);
611 return RET_BAD_STATUS;
612 }
613 hidInf_.descLength = character.length_;
614 LOG_DEBUG("[HOGP]%{public}s():descLength = 0x%{public}x", __FUNCTION__, hidInf_.descLength);
615 return BT_SUCCESS;
616 }
617
SaveReport(Characteristic character,Descriptor descriptor,Descriptor config)618 void HidHostHogp::SaveReport(Characteristic character, Descriptor descriptor, Descriptor config)
619 {
620 IProfileGattClient *gattClientService = GetGattClientService();
621 if (gattClientService == nullptr) {
622 LOG_ERROR("[HOGP] %{public}s:gattClientService is null.", __func__);
623 return;
624 }
625 if (descriptor.length_ != HID_HOST_REPORT_REFERENCE_SIZE) {
626 LOG_ERROR("[HOGP] %{public}s:descriptor length_ is error length=%{public}zu",
627 __func__, character.length_);
628 return;
629 }
630
631 reports_[character.handle_] = std::make_unique<HogpReport>();
632 reports_[character.handle_]->reportId = descriptor.value_[0];
633 reports_[character.handle_]->reportType = descriptor.value_[1];
634 reports_[character.handle_]->character = std::make_unique<Characteristic>(character);
635 reports_[character.handle_]->config = std::make_unique<Descriptor>(config);
636 LOG_DEBUG("[HOGP]%{public}s():reportId = 0x%{public}x,reportType = 0x%{public}x", __FUNCTION__,
637 reports_[character.handle_]->reportId, reports_[character.handle_]->reportType);
638 }
639
SetInputReportNotification()640 void HidHostHogp::SetInputReportNotification()
641 {
642 IProfileGattClient *gattClientService = GetGattClientService();
643 if (gattClientService == nullptr) {
644 LOG_ERROR("[HOGP] %{public}s:gattClientService is null.", __func__);
645 return;
646 }
647
648 for (auto iter = reports_.begin(); iter != reports_.end(); ++iter) {
649 if ((iter->second == nullptr) || (iter->second->reportType != HID_HOST_INPUT_REPORT)) {
650 break;
651 }
652 if ((iter->second->config == nullptr) || (iter->second->config->handle_ == 0)) {
653 LOG_ERROR("[HOGP] %{public}s:config is error ", __func__);
654 break;
655 }
656 std::unique_lock<std::mutex> lock(mutexWaitGattCallback_);
657 iter->second->config->length_ = HID_HOST_CLIENT_CHAR_CONFIG_SIZE;
658 iter->second->config->value_ = std::make_unique<uint8_t[]>(HID_HOST_CLIENT_CHAR_CONFIG_SIZE);
659 iter->second->config->value_[0] = 1;
660 iter->second->config->value_[1] = 0;
661 gattClientService->WriteDescriptor(appId_, *iter->second->config);
662 if (cvfull_.wait_for(lock,
663 std::chrono::seconds(HOGP_GATT_THREAD_WAIT_TIMEOUT)) == std::cv_status::timeout) {
664 LOG_ERROR("[HOGP] %{public}s:set report notifycation timeout", __func__);
665 }
666 }
667 }
668
ProcessEvent(const HidHostMessage & event)669 void HidHostHogp::ProcessEvent(const HidHostMessage &event)
670 {
671 LOG_DEBUG("[HOGP]%{public}s(): event %{public}s[%{public}d]",
672 __FUNCTION__, HidHostHogp::GetEventName(event.what_).c_str(), event.what_);
673
674 switch (event.what_) {
675 case HID_HOST_HOGP_CONNECTION_STATE_CHANGED_EVT:
676 OnConnectionStateChangedTask(event.arg1_);
677 break;
678 case HID_HOST_HOGP_SERVICES_DISCOVERED_EVT:
679 dispatcher_->Initialize();
680 dispatcher_->PostTask(std::bind(&HidHostHogp::OnServicesDiscoveredTask, this, event.arg1_));
681 break;
682 case HID_HOST_HOGP_STOP_THREAD_EVT:
683 dispatcher_->Uninitialize();
684 break;
685 default:
686 break;
687 }
688 }
689
GetEventName(int what)690 std::string HidHostHogp::GetEventName(int what)
691 {
692 switch (what) {
693 case HID_HOST_HOGP_CONNECTION_STATE_CHANGED_EVT:
694 return "HID_HOST_HOGP_CONNECTION_STATE_CHANGED_EVT";
695 case HID_HOST_HOGP_SERVICES_DISCOVERED_EVT:
696 return "HID_HOST_HOGP_SERVICES_DISCOVERED_EVT";
697 case HID_HOST_HOGP_STOP_THREAD_EVT:
698 return "HID_HOST_HOGP_STOP_THREAD_EVT";
699 default:
700 return "Unknown";
701 }
702 }
703
HogpGattClientCallback(HidHostHogp * hogp)704 HidHostHogp::HogpGattClientCallback::HogpGattClientCallback(HidHostHogp *hogp) : hogp_(hogp)
705 {}
706
OnConnectionStateChanged(int state,int newState)707 void HidHostHogp::HogpGattClientCallback::OnConnectionStateChanged(int state, int newState)
708 {
709 LOG_DEBUG("[HOGP]%{public}s state:%{public}d newState:%{public}d", __FUNCTION__, state, newState);
710 if (state != newState) {
711 HidHostMessage event(HID_HOST_HOGP_CONNECTION_STATE_CHANGED_EVT, newState);
712 event.dev_ = hogp_->address_;
713 HidHostService::GetService()->PostEvent(event);
714 }
715 }
716
OnServicesChanged(const std::vector<Service> & services)717 void HidHostHogp::HogpGattClientCallback::OnServicesChanged(const std::vector<Service> &services)
718 {
719 LOG_DEBUG("[HOGP]%{public}s", __FUNCTION__);
720 }
721
OnCharacteristicRead(int ret,const Characteristic & characteristic)722 void HidHostHogp::HogpGattClientCallback::OnCharacteristicRead(int ret, const Characteristic &characteristic)
723 {
724 LOG_DEBUG("[HOGP]%{public}s ret:%{public}d", __FUNCTION__, ret);
725 std::lock_guard<std::mutex> lock(hogp_->mutexWaitGattCallback_);
726 if (ret != GattStatus::GATT_SUCCESS) {
727 LOG_ERROR("[HOGP] %{public}s:ret=%{public}d", __func__, ret);
728 hogp_->characteristicTemp_ = nullptr;
729 } else {
730 hogp_->characteristicTemp_ = std::make_unique<Characteristic>(characteristic);
731 }
732 hogp_->cvfull_.notify_all();
733 }
734
OnCharacteristicWrite(int ret,const Characteristic & characteristic)735 void HidHostHogp::HogpGattClientCallback::OnCharacteristicWrite(int ret, const Characteristic &characteristic)
736 {
737 LOG_DEBUG("[HOGP]%{public}s ret:%{public}d", __FUNCTION__, ret);
738 std::lock_guard<std::mutex> lock(hogp_->mutexWaitGattCallback_);
739 if (ret != GattStatus::GATT_SUCCESS) {
740 LOG_ERROR("[HOGP] %{public}s:ret=%{public}d", __func__, ret);
741 hogp_->characteristicTemp_ = nullptr;
742 } else {
743 hogp_->characteristicTemp_ = std::make_unique<Characteristic>(characteristic);
744 }
745 hogp_->cvfull_.notify_all();
746 }
747
OnCharacteristicChanged(const Characteristic & characteristic)748 void HidHostHogp::HogpGattClientCallback::OnCharacteristicChanged(const Characteristic &characteristic)
749 {
750 LOG_DEBUG("[HOGP]%{public}s", __FUNCTION__);
751 uint8_t reportId = 0;
752 auto it = hogp_->reports_.find(characteristic.handle_);
753 if ((it != hogp_->reports_.end()) && (it->second != nullptr)) {
754 reportId = it->second->reportId;
755 } else {
756 LOG_ERROR("[HOGP]%{public}s():not find Characteristic[%{public}d]", __FUNCTION__, characteristic.handle_);
757 return;
758 }
759
760 if ((characteristic.value_ != nullptr) && (characteristic.length_ != 0)) {
761 HidHostMessage event(HID_HOST_INT_DATA_EVT);
762 event.dev_ = hogp_->address_;
763 int offset = 0;
764 if (reportId != 0) {
765 offset++;
766 event.dataLength_ = static_cast<int>(characteristic.length_ + offset);
767 event.data_ = std::make_unique<uint8_t[]>(event.dataLength_);
768 event.data_[0] = reportId;
769 } else {
770 event.dataLength_ = static_cast<int>(characteristic.length_);
771 event.data_ = std::make_unique<uint8_t[]>(event.dataLength_);
772 }
773 if (memcpy_s(event.data_.get() + offset, characteristic.length_,
774 characteristic.value_.get(), characteristic.length_) != EOK) {
775 LOG_ERROR("[HOGP]%{public}s():memcpy error", __FUNCTION__);
776 return;
777 }
778 HidHostService::GetService()->PostEvent(event);
779 } else {
780 LOG_ERROR("[HOGP]%{public}s():data is null length_=%{public}zu", __FUNCTION__, characteristic.length_);
781 }
782 }
783
OnDescriptorRead(int ret,const Descriptor & descriptor)784 void HidHostHogp::HogpGattClientCallback::OnDescriptorRead(int ret, const Descriptor &descriptor)
785 {
786 LOG_DEBUG("[HOGP]%{public}s ret:%{public}d, descriptor=%{public}d", __FUNCTION__, ret, descriptor.handle_);
787 std::lock_guard<std::mutex> lock(hogp_->mutexWaitGattCallback_);
788 if (ret != GattStatus::GATT_SUCCESS) {
789 LOG_ERROR("[HOGP] %{public}s:ret=%{public}d", __func__, ret);
790 hogp_->descriptorTemp_ = nullptr;
791 } else {
792 hogp_->descriptorTemp_ = std::make_unique<Descriptor>(descriptor);
793 }
794 hogp_->cvfull_.notify_all();
795 }
796
OnDescriptorWrite(int ret,const Descriptor & descriptor)797 void HidHostHogp::HogpGattClientCallback::OnDescriptorWrite(int ret, const Descriptor &descriptor)
798 {
799 LOG_DEBUG("[HOGP]%{public}s ret:%{public}d", __FUNCTION__, ret);
800 std::lock_guard<std::mutex> lock(hogp_->mutexWaitGattCallback_);
801 if (ret != GattStatus::GATT_SUCCESS) {
802 LOG_ERROR("[HOGP] %{public}s:ret=%{public}d", __func__, ret);
803 }
804 hogp_->cvfull_.notify_all();
805 }
806
OnMtuChanged(int state,int mtu)807 void HidHostHogp::HogpGattClientCallback::OnMtuChanged(int state, int mtu)
808 {
809 LOG_DEBUG("[HOGP]%{public}s state:%{public}d, mtu:%{public}d", __FUNCTION__, state, mtu);
810 }
811
OnConnectionParameterChanged(int interval,int latency,int timeout,int status)812 void HidHostHogp::HogpGattClientCallback::OnConnectionParameterChanged(
813 int interval, int latency, int timeout, int status)
814 {
815 LOG_DEBUG("[HOGP]%{public}s state:%{public}d, timeout:%{public}d", __FUNCTION__, status, timeout);
816 }
817
OnServicesDiscovered(int status)818 void HidHostHogp::HogpGattClientCallback::OnServicesDiscovered(int status)
819 {
820 LOG_DEBUG("[HOGP]%{public}s state:%{public}d", __FUNCTION__, status);
821 HidHostMessage event(HID_HOST_HOGP_SERVICES_DISCOVERED_EVT, status);
822 event.dev_ = hogp_->address_;
823 HidHostService::GetService()->PostEvent(event);
824 }
825
OnReadRemoteRssiValue(const RawAddress & addr,int rssi,int status)826 void HidHostHogp::HogpGattClientCallback::OnReadRemoteRssiValue(const RawAddress &addr, int rssi, int status)
827 {
828 return;
829 }
830 } // namespace bluetooth
831 } // namespace OHOS
832