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_service.h"
17 
18 #include "bluetooth_errorcode.h"
19 
20 namespace OHOS {
21 namespace bluetooth {
HidHostService()22 HidHostService::HidHostService() : utility::Context(PROFILE_NAME_HID_HOST, "1.1.1")
23 {
24     LOG_DEBUG("[HIDH Service]%{public}s:%{public}s Create", PROFILE_NAME_HID_HOST.c_str(), Name().c_str());
25 }
26 
~HidHostService()27 HidHostService::~HidHostService()
28 {
29     LOG_DEBUG("[HIDH Service]%{public}s:%{public}s Destroy", PROFILE_NAME_MAP_MSE.c_str(), Name().c_str());
30 }
31 
GetContext()32 utility::Context *HidHostService::GetContext()
33 {
34     return this;
35 }
36 
GetService()37 HidHostService *HidHostService::GetService()
38 {
39     auto servManager = IProfileManager::GetInstance();
40     return static_cast<HidHostService *>(servManager->GetProfileService(PROFILE_NAME_HID_HOST));
41 }
42 
RegisterObserver(IHidHostObserver & hidHostObserver)43 void HidHostService::RegisterObserver(IHidHostObserver &hidHostObserver)
44 {
45     LOG_DEBUG("[HIDH Service]%{public}s Enter", __FUNCTION__);
46 
47     hidHostObservers_.Register(hidHostObserver);
48 }
49 
DeregisterObserver(IHidHostObserver & hidHostObserver)50 void HidHostService::DeregisterObserver(IHidHostObserver &hidHostObserver)
51 {
52     LOG_DEBUG("[HIDH Service]%{public}s Enter", __FUNCTION__);
53 
54     hidHostObservers_.Deregister(hidHostObserver);
55 }
56 
NotifyStateChanged(const RawAddress & device,int state)57 void HidHostService::NotifyStateChanged(const RawAddress &device, int state)
58 {
59     // Reference "HID_HOST_STATE_CONNECTED"
60     LOG_DEBUG("[HIDH Service]%{public}s, state:%{public}d", __FUNCTION__, state);
61     int newState = stateMap_.at(state);
62 
63     hidHostObservers_.ForEach([device, newState](IHidHostObserver &observer) {
64         observer.OnConnectionStateChanged(device, newState);
65     });
66 }
67 
Enable(void)68 void HidHostService::Enable(void)
69 {
70     LOG_DEBUG("[HIDH Service]%{public}s Enter", __FUNCTION__);
71 
72     HidHostMessage event(HID_HOST_SERVICE_STARTUP_EVT);
73     PostEvent(event);
74 }
75 
Disable(void)76 void HidHostService::Disable(void)
77 {
78     LOG_DEBUG("[HIDH Service]%{public}s Enter", __FUNCTION__);
79 
80     HidHostMessage event(HID_HOST_SERVICE_SHUTDOWN_EVT);
81     PostEvent(event);
82 }
83 
StartUp()84 void HidHostService::StartUp()
85 {
86     LOG_DEBUG("[HIDH Service]%{public}s():==========<start>==========", __FUNCTION__);
87     if (isStarted_) {
88         GetContext()->OnEnable(PROFILE_NAME_HID_HOST, true);
89         LOG_WARN("[HIDH Service]%{public}s():HidHostService has already been started before.", __FUNCTION__);
90         return;
91     }
92 
93     maxConnectionsNum_ = GetMaxConnectionsDeviceNum();
94 
95     int ret = HidHostL2capConnection::Startup();
96 
97     GetContext()->OnEnable(PROFILE_NAME_HID_HOST, ret ? false : true);
98     if (ret == 0) {
99         isStarted_ = true;
100         LOG_DEBUG("[HIDH Service]%{public}s():HidHostService started", __FUNCTION__);
101     }
102 }
103 
ShutDown()104 void HidHostService::ShutDown()
105 {
106     LOG_DEBUG("[HIDH Service]%{public}s():==========<start>==========", __FUNCTION__);
107     if (!isStarted_) {
108         GetContext()->OnDisable(PROFILE_NAME_HID_HOST, true);
109         LOG_WARN("[HIDH Service]%{public}s():HidHostService has already been shutdown before.", __FUNCTION__);
110         return;
111     }
112 
113     isShuttingDown_ = true;
114     bool isDisconnected = false;
115     for (auto it = stateMachines_.begin(); it != stateMachines_.end(); ++it) {
116         if ((it->second != nullptr) && (it->second->GetDeviceStateInt() > HID_HOST_STATE_DISCONNECTED)) {
117             Disconnect(RawAddress(it->first));
118             isDisconnected = true;
119         }
120     }
121 
122     if (!isDisconnected) {
123         ShutDownDone(true);
124     }
125 }
126 
ShutDownDone(bool isAllDisconnected)127 void HidHostService::ShutDownDone(bool isAllDisconnected)
128 {
129     LOG_DEBUG("[HIDH Service]%{public}s():==========<start>==========", __FUNCTION__);
130     if (!isAllDisconnected) {
131         for (auto it = stateMachines_.begin(); it != stateMachines_.end(); ++it) {
132             if ((it->second != nullptr) && (it->second->GetDeviceStateInt() > HID_HOST_STATE_DISCONNECTED)) {
133                 return;
134             }
135         }
136     }
137 
138     stateMachines_.clear();
139 
140     HidHostL2capConnection::Shutdown();
141     GetContext()->OnDisable(PROFILE_NAME_HID_HOST, true);
142     isStarted_ = false;
143     LOG_DEBUG("[HIDH Service]%{public}s():HidHostService shutdown", __FUNCTION__);
144     isShuttingDown_ = false;
145 }
146 
Connect(const RawAddress & device)147 int HidHostService::Connect(const RawAddress &device)
148 {
149     LOG_DEBUG("[HIDH Service]%{public}s Enter", __FUNCTION__);
150 
151     std::lock_guard<std::recursive_mutex> lk(mutex_);
152     std::string address = device.GetAddress();
153     auto it = stateMachines_.find(address);
154     if ((it != stateMachines_.end()) && (it->second != nullptr)) {
155         int slcState = it->second->GetDeviceStateInt();
156         if ((slcState >= HID_HOST_STATE_CONNECTED) || (slcState == HID_HOST_STATE_CONNECTING)) {
157             return Bluetooth::BT_ERR_INTERNAL_ERROR;
158         }
159     }
160 
161     if (GetConnectionsDeviceNum() >= maxConnectionsNum_) {
162         LOG_INFO("[HIDH Service]%{public}s():Max connection number has reached!", __FUNCTION__);
163         return Bluetooth::BT_ERR_INTERNAL_ERROR;
164     }
165 
166     HidHostMessage event(HID_HOST_API_OPEN_EVT);
167     event.dev_ = address;
168     PostEvent(event);
169     return HID_HOST_SUCCESS;
170 }
171 
Disconnect(const RawAddress & device)172 int HidHostService::Disconnect(const RawAddress &device)
173 {
174     LOG_DEBUG("[HIDH Service]%{public}s Enter", __FUNCTION__);
175 
176     std::lock_guard<std::recursive_mutex> lk(mutex_);
177     std::string address = device.GetAddress();
178     auto it = stateMachines_.find(address);
179     if (it == stateMachines_.end() || it->second == nullptr) {
180         LOG_DEBUG("[HIDH Service]%{public}s():The state machine is not available!", __FUNCTION__);
181         return Bluetooth::BT_ERR_INTERNAL_ERROR;
182     }
183 
184     int slcState = it->second->GetDeviceStateInt();
185     if ((slcState != HID_HOST_STATE_CONNECTING) && (slcState < HID_HOST_STATE_CONNECTED)) {
186         LOG_DEBUG("[HIDH Service]%{public}s():slcState:%{public}d", __FUNCTION__, slcState);
187         return Bluetooth::BT_ERR_INTERNAL_ERROR;
188     }
189 
190     HidHostMessage event(HID_HOST_API_CLOSE_EVT);
191     event.dev_ = address;
192     PostEvent(event);
193     return HID_HOST_SUCCESS;
194 }
195 
HidHostVCUnplug(std::string device,uint8_t id,uint16_t size,uint8_t type)196 int HidHostService::HidHostVCUnplug(std::string device, uint8_t id, uint16_t size, uint8_t type)
197 {
198     HidHostMessage event(HID_HOST_API_WRITE_DEV_EVT);
199     event.dev_ = device;
200     event.sendData_.type = HID_HOST_DATA_TYPE_CONTROL;
201     event.sendData_.param = type;
202     event.sendData_.data = size;
203     event.sendData_.reportId = id;
204     PostEvent(event);
205     return HID_HOST_SUCCESS;
206 }
207 
HidHostSendData(std::string device,uint8_t id,uint16_t size,uint8_t type)208 int HidHostService::HidHostSendData(std::string device, uint8_t id, uint16_t size, uint8_t type)
209 {
210     HidHostMessage event(HID_HOST_API_WRITE_DEV_EVT);
211     event.dev_ = device;
212     event.sendData_.type = HID_HOST_DATA_TYPE_DATA;
213     event.sendData_.param = type;
214     event.sendData_.data = size;
215     event.sendData_.reportId = id;
216     PostEvent(event);
217     return HID_HOST_SUCCESS;
218 }
219 
HidHostSetReport(std::string device,uint8_t type,uint16_t size,const uint8_t * report)220 int HidHostService::HidHostSetReport(std::string device, uint8_t type, uint16_t size, const uint8_t* report)
221 {
222     HidHostMessage event(HID_HOST_API_WRITE_DEV_EVT);
223     event.dev_ = device;
224     event.sendData_.type = HID_HOST_DATA_TYPE_SET_REPORT;
225     event.sendData_.param = type;
226     event.sendData_.data = 0;
227     event.sendData_.reportId = 0;
228     if ((size > 0) && (report != nullptr)) {
229         event.dataLength_ = static_cast<int>(size);
230         event.data_ = std::make_unique<uint8_t[]>(size);
231         if (memcpy_s(event.data_.get(), size, report, size) != EOK) {
232             LOG_ERROR("[HIDH Service]%{public}s():memcpy error", __FUNCTION__);
233             return Bluetooth::BT_ERR_INTERNAL_ERROR;
234         }
235     }
236     PostEvent(event);
237     return HID_HOST_SUCCESS;
238 }
239 
HidHostGetReport(std::string device,uint8_t id,uint16_t size,uint8_t type)240 int HidHostService::HidHostGetReport(std::string device, uint8_t id, uint16_t size, uint8_t type)
241 {
242     HidHostMessage event(HID_HOST_API_WRITE_DEV_EVT);
243     event.dev_ = device;
244     event.sendData_.type = HID_HOST_DATA_TYPE_GET_REPORT;
245     event.sendData_.param = type;
246     event.sendData_.data = size;
247     event.sendData_.reportId = id;
248     PostEvent(event);
249     return HID_HOST_SUCCESS;
250 }
251 
IsConnected(const std::string & address) const252 bool HidHostService::IsConnected(const std::string &address) const
253 {
254     LOG_INFO("[HIDH Service] IsConnected start");
255 
256     auto it = stateMachines_.find(address);
257     if (it == stateMachines_.end() || it->second == nullptr) {
258         HILOGE("[HIDH Service] IsConnected:Invalid Device address:%{public}s", GetEncryptAddr(address).c_str());
259         return false;
260     }
261     if (it->second->GetDeviceStateInt() < HID_HOST_STATE_CONNECTED) {
262         LOG_INFO("[HIDH Service] IsConnected:false");
263         return false;
264     }
265     return true;
266 }
267 
GetDevicesByStates(std::vector<int> states)268 std::vector<RawAddress> HidHostService::GetDevicesByStates(std::vector<int> states)
269 {
270     LOG_INFO("[HIDH Service] GetDevicesByStates Enter");
271     std::lock_guard<std::recursive_mutex> lk(mutex_);
272     std::vector<RawAddress> devices;
273     for (auto it = stateMachines_.begin(); it != stateMachines_.end(); ++it) {
274         RawAddress device(it->first);
275         for (size_t i = 0; i < states.size(); i++) {
276             if (GetDeviceState(device) == states[i]) {
277                 devices.push_back(device);
278                 break;
279             }
280         }
281     }
282     return devices;
283 }
284 
GetDeviceState(const RawAddress & device)285 int HidHostService::GetDeviceState(const RawAddress &device)
286 {
287     LOG_INFO("[HIDH Service] GetDeviceState start");
288     std::lock_guard<std::recursive_mutex> lk(mutex_);
289     std::string address = device.GetAddress();
290     auto it = stateMachines_.find(address);
291     if (it == stateMachines_.end() || it->second == nullptr) {
292         LOG_INFO("[HID HOST]GetDeviceState:The state machine is not available!");
293         return stateMap_.at(HID_HOST_STATE_DISCONNECTED);
294     }
295 
296     int state = it->second->GetDeviceStateInt();
297     LOG_INFO("[HIDH Service] GetDeviceState, state:%{public}d", state);
298     if (state >= HID_HOST_STATE_CONNECTED) {
299         return stateMap_.at(HID_HOST_STATE_CONNECTED);
300     } else {
301         return stateMap_.at(state);
302     }
303 }
304 
GetConnectDevices(void)305 std::list<RawAddress> HidHostService::GetConnectDevices(void)
306 {
307     LOG_INFO("[HIDH Service] GetConnectDevices Enter");
308     std::lock_guard<std::recursive_mutex> lk(mutex_);
309     std::list<RawAddress> devList;
310     for (auto it = stateMachines_.begin(); it != stateMachines_.end(); ++it) {
311         if ((it->second != nullptr) && (it->second->GetDeviceStateInt() >= HID_HOST_STATE_CONNECTED)) {
312             devList.push_back(RawAddress(it->first));
313         }
314     }
315     return devList;
316 }
317 
GetConnectState(void)318 int HidHostService::GetConnectState(void)
319 {
320     LOG_INFO("[HIDH Service] GetConnectState Enter");
321     int result = 0;
322     std::lock_guard<std::recursive_mutex> lk(mutex_);
323     for (auto it = stateMachines_.begin(); it != stateMachines_.end(); ++it) {
324         if (it->second == nullptr) {
325             result |= PROFILE_STATE_DISCONNECTED;
326         } else if (it->second->GetDeviceStateInt() >= HID_HOST_STATE_CONNECTED) {
327             result |= PROFILE_STATE_CONNECTED;
328         } else if (it->second->GetDeviceStateInt() == HID_HOST_STATE_CONNECTING) {
329             result |= PROFILE_STATE_CONNECTING;
330         } else if (it->second->GetDeviceStateInt() == HID_HOST_STATE_DISCONNECTING) {
331             result |= PROFILE_STATE_DISCONNECTING;
332         } else if (it->second->GetDeviceStateInt() == HID_HOST_STATE_DISCONNECTED) {
333             result |= PROFILE_STATE_DISCONNECTED;
334         }
335     }
336     LOG_INFO("[HIDH Service] GetConnectState result:%{public}d", result);
337     return result;
338 }
339 
GetMaxConnectNum(void)340 int HidHostService::GetMaxConnectNum(void)
341 {
342     std::lock_guard<std::recursive_mutex> lk(mutex_);
343     LOG_INFO("[HIDH Service] GetMaxConnectNum:%{public}d", maxConnectionsNum_);
344     return maxConnectionsNum_;
345 }
346 
GetConnectionsDeviceNum() const347 int HidHostService::GetConnectionsDeviceNum() const
348 {
349     int size = 0;
350     for (auto iter = stateMachines_.begin(); iter != stateMachines_.end(); ++iter) {
351         if (iter->second != nullptr) {
352             auto connectionState = iter->second->GetDeviceStateInt();
353             if ((connectionState == HID_HOST_STATE_CONNECTING) || (connectionState >= HID_HOST_STATE_CONNECTED)) {
354                 size++;
355             }
356         }
357     }
358     return size;
359 }
360 
GetMaxConnectionsDeviceNum() const361 int HidHostService::GetMaxConnectionsDeviceNum() const
362 {
363     int number = HID_HOST_MAX_DEFAULT_CONNECTIONS_NUMR;
364     if (!AdapterConfig::GetInstance()->GetValue(SECTION_HID_HOST_SERVICE, PROPERTY_MAX_CONNECTED_DEVICES, number)) {
365         LOG_INFO("[HIDH Service] GetMaxConnectionsDeviceNum failed");
366     }
367     return number;
368 }
369 
RemoveStateMachine(const std::string & device)370 void HidHostService::RemoveStateMachine(const std::string &device)
371 {
372     HidHostMessage event(HID_HOST_REMOVE_STATE_MACHINE_EVT);
373     event.dev_ = device;
374     PostEvent(event);
375 }
376 
PostEvent(const HidHostMessage & event)377 void HidHostService::PostEvent(const HidHostMessage &event)
378 {
379     GetDispatcher()->PostTask(std::bind(&HidHostService::ProcessEvent, this, event));
380 }
381 
ProcessEvent(const HidHostMessage & event)382 void HidHostService::ProcessEvent(const HidHostMessage &event)
383 {
384     std::lock_guard<std::recursive_mutex> lk(mutex_);
385     std::string address = event.dev_;
386     HILOGI("[HIDH Service] ProcessEvent:address[%{public}s], event_no[%{public}d]",
387         GetEncryptAddr(address).c_str(), event.what_);
388     switch (event.what_) {
389         case HID_HOST_SERVICE_STARTUP_EVT:
390             StartUp();
391             break;
392         case HID_HOST_SERVICE_SHUTDOWN_EVT:
393             ShutDown();
394             break;
395         case HID_HOST_API_OPEN_EVT:
396         case HID_HOST_L2CAP_CONNECT_REQ_EVT:
397             ProcessConnectEvent(event);
398             break;
399         case HID_HOST_REMOVE_STATE_MACHINE_EVT:
400             ProcessRemoveStateMachine(event.dev_);
401             break;
402         default:
403             ProcessDefaultEvent(event);
404             break;
405     }
406 }
407 
ProcessConnectEvent(const HidHostMessage & event)408 void HidHostService::ProcessConnectEvent(const HidHostMessage &event)
409 {
410     if (GetConnectionsDeviceNum() < maxConnectionsNum_) {
411         auto it = stateMachines_.find(event.dev_);
412         if (it != stateMachines_.end() && it->second != nullptr && it->second->IsRemoving()) {
413             // peer device may send connect request before we remove statemachine for last connection.
414             // so post this connect request, process it after we remove statemachine completely.
415             PostEvent(event);
416         } else if (it == stateMachines_.end() || it->second == nullptr) {
417             stateMachines_[event.dev_] = std::make_unique<HidHostStateMachine>(event.dev_);
418             stateMachines_[event.dev_]->Init();
419             stateMachines_[event.dev_]->ProcessMessage(event);
420             if (event.what_ == HID_HOST_L2CAP_CONNECT_REQ_EVT) {
421                 stateMachines_[event.dev_]->ProcessL2capConnectionEvent(event);
422             }
423         } else {
424             it->second->ProcessMessage(event);
425             if (event.what_ == HID_HOST_L2CAP_CONNECT_REQ_EVT) {
426                 it->second->ProcessL2capConnectionEvent(event);
427             }
428         }
429     }
430 }
431 
HidHostFindDeviceByLcid(uint16_t lcid,bool * isControlLcid)432 std::string HidHostService::HidHostFindDeviceByLcid(uint16_t lcid, bool *isControlLcid)
433 {
434     std::string ret;
435 
436     std::lock_guard<std::recursive_mutex> lk(mutex_);
437     for (auto it = stateMachines_.begin(); it != stateMachines_.end(); ++it) {
438         if ((it->second != nullptr) && ((it->second->GetDeviceControlLcid() == lcid) ||
439                 (it->second->GetDeviceInterruptLcid() == lcid))) {
440             if (it->second->GetDeviceControlLcid() == lcid) {
441                 *isControlLcid = true;
442             }
443             return it->first;
444         }
445     }
446     return ret;
447 }
448 
ProcessRemoveStateMachine(const std::string & address)449 void HidHostService::ProcessRemoveStateMachine(const std::string &address)
450 {
451     stateMachines_.insert_or_assign(address, nullptr);
452     if (isShuttingDown_) {
453         ShutDownDone(false);
454     }
455 }
456 
ProcessDefaultEvent(const HidHostMessage & event) const457 void HidHostService::ProcessDefaultEvent(const HidHostMessage &event) const
458 {
459     auto it = stateMachines_.find(event.dev_);
460     if ((it != stateMachines_.end()) && (it->second != nullptr)) {
461         if ((event.what_ > HID_HOST_L2CAP_START_EVT) && (event.what_ < HID_HOST_L2CAP_END_EVT)) {
462             it->second->ProcessL2capConnectionEvent(event);
463         } else if ((event.what_ > HID_HOST_HOGP_START_EVT) && (event.what_ < HID_HOST_HOGP_END_EVT)) {
464             it->second->ProcessHogpEvent(event);
465         } else {
466             it->second->ProcessMessage(event);
467         }
468     } else {
469         HILOGE("[HIDH Service] ProcessDefaultEvent:invalid address[%{public}s]", GetEncryptAddr(event.dev_).c_str());
470     }
471 }
472 REGISTER_CLASS_CREATOR(HidHostService);
473 }  // namespace bluetooth
474 }  // namespace OHOS
475