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