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