1 /*
2 * Copyright (c) 2021-2024 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 "input_hub.h"
17
18 #include <algorithm>
19 #include <cinttypes>
20 #include <cstring>
21 #include <fcntl.h>
22 #include <filesystem>
23 #include <regex>
24 #include <securec.h>
25 #include <sstream>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <thread>
29 #include <unistd.h>
30 #include <utility>
31
32 #include "constants_dinput.h"
33 #include "dinput_context.h"
34 #include "dinput_errcode.h"
35 #include "dinput_log.h"
36 #include "dinput_sink_state.h"
37 #include "dinput_utils_tool.h"
38
39 namespace OHOS {
40 namespace DistributedHardware {
41 namespace DistributedInput {
42 namespace {
43 const uint32_t SLEEP_TIME_US = 100 * 1000;
44 const std::string MOUSE_NODE_KEY = "mouse";
45 const uint32_t SPACELENGTH = 1024;
46 }
47
InputHub(bool isPluginMonitor)48 InputHub::InputHub(bool isPluginMonitor) : epollFd_(-1), iNotifyFd_(-1), inputWd_(-1),
49 isPluginMonitor_(isPluginMonitor), needToScanDevices_(true), mPendingEventItems{},
50 pendingEventCount_(0), pendingEventIndex_(0), pendingINotify_(false), deviceChanged_(false),
51 inputTypes_(0), isStartCollectEvent_(false), isStartCollectHandler_(false)
52 {
53 Initialize();
54 }
55
~InputHub()56 InputHub::~InputHub()
57 {
58 Release();
59 }
60
Initialize()61 int32_t InputHub::Initialize()
62 {
63 epollFd_ = epoll_create1(EPOLL_CLOEXEC);
64 if (epollFd_ < 0) {
65 DHLOGE("Could not create epoll instance: %{public}s", ConvertErrNo().c_str());
66 return ERR_DH_INPUT_HUB_EPOLL_INIT_FAIL;
67 }
68
69 if (isPluginMonitor_) {
70 DHLOGI("Init InputHub for device plugin monitor");
71 iNotifyFd_ = inotify_init();
72 inputWd_ = inotify_add_watch(iNotifyFd_, DEVICE_PATH, IN_DELETE | IN_CREATE);
73 if (inputWd_ < 0) {
74 DHLOGE("Could not register INotify for %{public}s: %{public}s", DEVICE_PATH, ConvertErrNo().c_str());
75 return ERR_DH_INPUT_HUB_EPOLL_INIT_FAIL;
76 }
77
78 struct epoll_event eventItem = {};
79 eventItem.events = EPOLLIN;
80 eventItem.data.fd = iNotifyFd_;
81 int result = epoll_ctl(epollFd_, EPOLL_CTL_ADD, iNotifyFd_, &eventItem);
82 if (result != 0) {
83 DHLOGE("Could not add INotify to epoll instance. errno=%{public}d", errno);
84 return ERR_DH_INPUT_HUB_EPOLL_INIT_FAIL;
85 }
86 } else {
87 DHLOGI("Init InputHub for read device events");
88 }
89
90 return DH_SUCCESS;
91 }
92
Release()93 int32_t InputHub::Release()
94 {
95 CloseAllDevicesLocked();
96 if (epollFd_ != -1) {
97 ::close(epollFd_);
98 epollFd_ = -1;
99 }
100
101 if (iNotifyFd_ != -1) {
102 ::close(iNotifyFd_);
103 iNotifyFd_ = -1;
104 }
105
106 if (isPluginMonitor_) {
107 StopCollectInputHandler();
108 } else {
109 StopCollectInputEvents();
110 }
111
112 sharedDHIds_.clear();
113 logTimesMap_.clear();
114 return DH_SUCCESS;
115 }
116
IsInputNodeNoNeedScan(const std::string & path)117 bool InputHub::IsInputNodeNoNeedScan(const std::string &path)
118 {
119 {
120 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
121 auto iter = devices_.find(path);
122 if (iter != devices_.end()) {
123 return true;
124 }
125 }
126
127 if (path.find(MOUSE_NODE_KEY) != std::string::npos) {
128 return true;
129 }
130
131 return IsSkipDevicePath(path);
132 }
133
ScanAndRecordInputDevices()134 void InputHub::ScanAndRecordInputDevices()
135 {
136 ScanInputDevices(DEVICE_PATH);
137
138 {
139 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
140 while (!openingDevices_.empty()) {
141 std::unique_ptr<Device> device = std::move(*openingDevices_.rbegin());
142 openingDevices_.pop_back();
143 DHLOGI("Reporting device opened: path=%{public}s, name=%{public}s\n",
144 device->path.c_str(), device->identifier.name.c_str());
145 std::string devPath = device->path;
146 auto [dev_it, inserted] = devices_.insert_or_assign(device->path, std::move(device));
147 if (!inserted) {
148 DHLOGI("Device with this path %{public}s exists, replaced. \n", devPath.c_str());
149 }
150 }
151 }
152 }
153
StartCollectInputEvents(RawEvent * buffer,size_t bufferSize)154 size_t InputHub::StartCollectInputEvents(RawEvent *buffer, size_t bufferSize)
155 {
156 size_t count = 0;
157 isStartCollectEvent_ = true;
158 while (isStartCollectEvent_) {
159 ScanAndRecordInputDevices();
160 count = GetEvents(buffer, bufferSize);
161 if (count > 0) {
162 break;
163 }
164
165 if (RefreshEpollItem(false) < 0) {
166 break;
167 }
168 }
169
170 // All done, return the number of events we read.
171 return count;
172 }
173
StopCollectInputEvents()174 void InputHub::StopCollectInputEvents()
175 {
176 DHLOGI("Stop Collect Input Events Thread");
177 isStartCollectEvent_ = false;
178 }
179
GetEvents(RawEvent * buffer,size_t bufferSize)180 size_t InputHub::GetEvents(RawEvent *buffer, size_t bufferSize)
181 {
182 RawEvent* event = buffer;
183 size_t capacity = bufferSize;
184 while (pendingEventIndex_ < pendingEventCount_) {
185 std::lock_guard<std::mutex> my_lock(operationMutex_);
186 const struct epoll_event& eventItem = mPendingEventItems[pendingEventIndex_++];
187 if (eventItem.data.fd == iNotifyFd_) {
188 continue;
189 }
190 struct input_event readBuffer[bufferSize];
191 int32_t readSize = read(eventItem.data.fd, readBuffer, sizeof(struct input_event) * capacity);
192 Device* deviceByFd = GetDeviceByFdLocked(eventItem.data.fd);
193 if (!deviceByFd) {
194 DHLOGE("Find device by fd: %{public}d failed", eventItem.data.fd);
195 continue;
196 }
197 size_t count = ReadInputEvent(readSize, *deviceByFd);
198 Device* device = GetSupportDeviceByFd(eventItem.data.fd);
199 if (!device) {
200 DHLOGE("Can not find device by fd: %{public}d", eventItem.data.fd);
201 continue;
202 }
203 if (!sharedDHIds_[device->identifier.descriptor]) {
204 RecordDeviceChangeStates(device, readBuffer, count);
205 DHLOGD("Not in sharing stat, device descriptor: %{public}s",
206 GetAnonyString(device->identifier.descriptor).c_str());
207 continue;
208 }
209 if (eventItem.events & EPOLLIN) {
210 event += CollectEvent(event, capacity, device, readBuffer, count);
211
212 if (capacity == 0) {
213 pendingEventIndex_ -= 1;
214 break;
215 }
216 } else if (eventItem.events & EPOLLHUP) {
217 DHLOGI("Removing device %{public}s due to epoll hang-up event.", device->identifier.name.c_str());
218 CloseDeviceLocked(*device);
219 }
220 }
221 return event - buffer;
222 }
223
IsCuror(Device * device)224 bool InputHub::IsCuror(Device *device)
225 {
226 return device->classes & INPUT_DEVICE_CLASS_CURSOR;
227 }
228
IsTouchPad(Device * device)229 bool InputHub::IsTouchPad(Device *device)
230 {
231 return ((device->classes & INPUT_DEVICE_CLASS_TOUCH_MT) || (device->classes & INPUT_DEVICE_CLASS_TOUCH)) &&
232 IsTouchPad(device->identifier);
233 }
234
IsTouchPad(const InputDevice & inputDevice)235 bool InputHub::IsTouchPad(const InputDevice &inputDevice)
236 {
237 std::string dhName = inputDevice.name;
238 transform(dhName.begin(), dhName.end(), dhName.begin(), ::tolower);
239 if (dhName.find(DH_TOUCH_PAD) == std::string::npos) {
240 return false;
241 }
242 return true;
243 }
244
MatchAndDealEvent(Device * device,const RawEvent & event)245 void InputHub::MatchAndDealEvent(Device *device, const RawEvent &event)
246 {
247 bool isTouchPad = IsTouchPad(device);
248 if (!isTouchPad) {
249 // Deal Normal key state, such as keys of keyboard or mouse
250 DealNormalKeyEvent(device, event);
251 } else {
252 // Deal TouchPad events
253 DealTouchPadEvent(event);
254 }
255 }
256
DealTouchPadEvent(const RawEvent & event)257 void InputHub::DealTouchPadEvent(const RawEvent &event)
258 {
259 auto ret = DInputSinkState::GetInstance().GetTouchPadEventFragMgr()->PushEvent(event.descriptor, event);
260 if (ret.first) {
261 DInputSinkState::GetInstance().SimulateTouchPadStateReset(ret.second);
262 }
263 }
264
DealNormalKeyEvent(Device * device,const RawEvent & event)265 void InputHub::DealNormalKeyEvent(Device *device, const RawEvent &event)
266 {
267 if (event.type == EV_KEY && event.value == KEY_DOWN_STATE) {
268 DInputSinkState::GetInstance().AddKeyDownState(event);
269 RecordChangeEventLog(event);
270 }
271 if (event.type == EV_KEY && event.value == KEY_UP_STATE) {
272 // Deal mouse left keydown reset
273 if (IsCuror(device) && event.code == BTN_MOUSE &&
274 !DInputSinkState::GetInstance().IsDhIdDown(event.descriptor)) {
275 DHLOGI("Find mouse BTN_MOUSE UP state that not down effective at sink side, dhId: %{public}s",
276 GetAnonyString(event.descriptor).c_str());
277 DInputSinkState::GetInstance().SimulateMouseBtnMouseUpState(event.descriptor, event);
278 }
279 DInputSinkState::GetInstance().RemoveKeyDownState(event);
280 RecordChangeEventLog(event);
281 }
282 if (event.type == EV_KEY && event.value == KEY_REPEAT) {
283 DInputSinkState::GetInstance().CheckAndSetLongPressedKeyOrder(event);
284 }
285 }
286
RecordDeviceChangeStates(Device * device,struct input_event readBuffer[],const size_t count)287 void InputHub::RecordDeviceChangeStates(Device *device, struct input_event readBuffer[], const size_t count)
288 {
289 bool isTouchEvent = false;
290 if ((device->classes & INPUT_DEVICE_CLASS_TOUCH_MT) || (device->classes & INPUT_DEVICE_CLASS_TOUCH)) {
291 if (!IsTouchPad(device->identifier)) {
292 isTouchEvent = true;
293 }
294 }
295
296 for (size_t i = 0; i < count; i++) {
297 const struct input_event& iev = readBuffer[i];
298 RawEvent event;
299 event.when = ProcessEventTimestamp(iev);
300 event.type = iev.type;
301 event.code = iev.code;
302 event.value = iev.value;
303 event.path = device->path;
304 event.descriptor = isTouchEvent ? touchDescriptor : device->identifier.descriptor;
305 MatchAndDealEvent(device, event);
306 }
307 }
308
CollectEvent(RawEvent * buffer,size_t & capacity,Device * device,struct input_event readBuffer[],const size_t count)309 size_t InputHub::CollectEvent(RawEvent *buffer, size_t &capacity, Device *device, struct input_event readBuffer[],
310 const size_t count)
311 {
312 std::vector<bool> needFilted(capacity, false);
313 bool isTouchEvent = false;
314 if ((device->classes & INPUT_DEVICE_CLASS_TOUCH_MT) || (device->classes & INPUT_DEVICE_CLASS_TOUCH)) {
315 if (!IsTouchPad(device->identifier)) {
316 isTouchEvent = true;
317 HandleTouchScreenEvent(readBuffer, count, needFilted);
318 }
319 }
320
321 RawEvent* event = buffer;
322 for (size_t i = 0; i < count; i++) {
323 if (needFilted[i]) {
324 continue;
325 }
326 const struct input_event& iev = readBuffer[i];
327 event->when = ProcessEventTimestamp(iev);
328 event->type = iev.type;
329 event->code = iev.code;
330 event->value = iev.value;
331 event->path = device->path;
332 event->descriptor = isTouchEvent ? touchDescriptor : device->identifier.descriptor;
333 RecordEventLog(event);
334 event += 1;
335 capacity -= 1;
336 if (capacity == 0) {
337 break;
338 }
339 }
340 return event - buffer;
341 }
342
ReadInputEvent(int32_t readSize,Device & device)343 size_t InputHub::ReadInputEvent(int32_t readSize, Device &device)
344 {
345 size_t count = 0;
346 if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
347 // Device was removed before INotify noticed.
348 DHLOGE("could not get event, removed? (fd: %{public}d size: %{public}d, errno: %{public}d)\n",
349 device.fd, readSize, errno);
350 CloseDeviceLocked(device);
351 } else if (readSize < 0) {
352 if (errno != EAGAIN && errno != EINTR) {
353 DHLOGW("could not get event (errno=%{public}d)", errno);
354 }
355 } else if ((readSize % sizeof(struct input_event)) != 0) {
356 DHLOGW("could not get event (wrong size: %{public}d)", readSize);
357 } else {
358 count = size_t(readSize) / sizeof(struct input_event);
359 return count;
360 }
361 return count;
362 }
363
DeviceIsExists(InputDeviceEvent * buffer,size_t bufferSize)364 size_t InputHub::DeviceIsExists(InputDeviceEvent *buffer, size_t bufferSize)
365 {
366 InputDeviceEvent* event = buffer;
367 size_t capacity = bufferSize;
368 // Report any devices that had last been added/removed.
369 {
370 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
371 for (auto it = closingDevices_.begin(); it != closingDevices_.end();) {
372 std::unique_ptr<Device> device = std::move(*it);
373 DHLOGI("Reporting device closed: id=%{public}s, name=%{public}s",
374 device->path.c_str(), device->identifier.name.c_str());
375 event->type = DeviceType::DEVICE_REMOVED;
376 event->deviceInfo = device->identifier;
377 event += 1;
378 it = closingDevices_.erase(it);
379 if (capacity == 0) {
380 break;
381 }
382 capacity--;
383 }
384 }
385
386 if (needToScanDevices_) {
387 needToScanDevices_ = false;
388 ScanInputDevices(DEVICE_PATH);
389 }
390
391 {
392 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
393 while (!openingDevices_.empty()) {
394 std::unique_ptr<Device> device = std::move(*openingDevices_.rbegin());
395 openingDevices_.pop_back();
396 DHLOGI("Reporting device opened: id=%{public}s, name=%{public}s",
397 device->path.c_str(), device->identifier.name.c_str());
398 event->type = DeviceType::DEVICE_ADDED;
399 event->deviceInfo = device->identifier;
400 event += 1;
401
402 std::string devPath = device->path;
403 auto [dev_it, inserted] = devices_.insert_or_assign(device->path, std::move(device));
404 if (!inserted) {
405 DHLOGI("Device path %{public}s exists, replaced.", devPath.c_str());
406 }
407 if (capacity == 0) {
408 break;
409 }
410 capacity--;
411 }
412 }
413 return event - buffer;
414 }
415
StartCollectInputHandler(InputDeviceEvent * buffer,size_t bufferSize)416 size_t InputHub::StartCollectInputHandler(InputDeviceEvent *buffer, size_t bufferSize)
417 {
418 size_t count = 0;
419 isStartCollectHandler_ = true;
420 while (isStartCollectHandler_) {
421 count = DeviceIsExists(buffer, bufferSize);
422 deviceChanged_ = false;
423 GetDeviceHandler();
424
425 if (pendingINotify_ && pendingEventIndex_ >= pendingEventCount_) {
426 pendingINotify_ = false;
427 ReadNotifyLocked();
428 deviceChanged_ = true;
429 }
430
431 // Report added or removed devices immediately.
432 if (deviceChanged_) {
433 continue;
434 }
435 if (count > 0) {
436 break;
437 }
438 if (RefreshEpollItem(true) < 0) {
439 break;
440 }
441 }
442
443 // All done, return the number of events we read.
444 return count;
445 }
446
StopCollectInputHandler()447 void InputHub::StopCollectInputHandler()
448 {
449 DHLOGI("Stop Collect Input Handler Thread");
450 isStartCollectHandler_ = false;
451 }
452
GetDeviceHandler()453 void InputHub::GetDeviceHandler()
454 {
455 while (pendingEventIndex_ < pendingEventCount_) {
456 std::lock_guard<std::mutex> my_lock(operationMutex_);
457 const struct epoll_event& eventItem = mPendingEventItems[pendingEventIndex_++];
458 if (eventItem.data.fd == iNotifyFd_) {
459 if (eventItem.events & EPOLLIN) {
460 pendingINotify_ = true;
461 } else {
462 DHLOGI("Received unexpected epoll event 0x%08x for INotify.", eventItem.events);
463 }
464 continue;
465 }
466
467 if (eventItem.events & EPOLLHUP) {
468 Device* device = GetDeviceByFdLocked(eventItem.data.fd);
469 if (!device) {
470 DHLOGE("Received unexpected epoll event 0x%{public}08x for unknown fd %{public}d.",
471 eventItem.events, eventItem.data.fd);
472 continue;
473 }
474 DHLOGI("Removing device %{public}s due to epoll hang-up event.", device->identifier.name.c_str());
475 deviceChanged_ = true;
476 CloseDeviceLocked(*device);
477 }
478 }
479 }
480
RefreshEpollItem(bool isSleep)481 int32_t InputHub::RefreshEpollItem(bool isSleep)
482 {
483 pendingEventIndex_ = 0;
484 int pollResult = epoll_wait(epollFd_, mPendingEventItems, EPOLL_MAX_EVENTS, EPOLL_WAITTIME);
485 if (pollResult == 0) {
486 // Timed out.
487 pendingEventCount_ = 0;
488 return ERR_DH_INPUT_HUB_EPOLL_WAIT_TIMEOUT;
489 }
490
491 if (pollResult < 0) {
492 // An error occurred.
493 pendingEventCount_ = 0;
494
495 // Sleep after errors to avoid locking up the system.
496 // Hopefully the error is transient.
497 if (errno != EINTR) {
498 DHLOGE("poll failed (errno=%{public}d)\n", errno);
499 usleep(SLEEP_TIME_US);
500 }
501 } else {
502 // Some events occurred.
503 pendingEventCount_ = pollResult;
504 }
505 if (isSleep) {
506 usleep(SLEEP_TIME_US);
507 }
508 return DH_SUCCESS;
509 }
510
GetAllInputDevices()511 std::vector<InputDevice> InputHub::GetAllInputDevices()
512 {
513 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
514 std::vector<InputDevice> vecDevice;
515 for (const auto &[id, device] : devices_) {
516 vecDevice.push_back(device->identifier);
517 }
518 return vecDevice;
519 }
520
ScanInputDevices(const std::string & dirName)521 void InputHub::ScanInputDevices(const std::string &dirName)
522 {
523 std::vector<std::string> inputDevPaths;
524 ScanInputDevicesPath(dirName, inputDevPaths);
525 for (const auto &tempPath: inputDevPaths) {
526 if (IsInputNodeNoNeedScan(tempPath)) {
527 continue;
528 }
529 OpenInputDeviceLocked(tempPath);
530 }
531 }
532
IsDeviceRegistered(const std::string & devicePath)533 bool InputHub::IsDeviceRegistered(const std::string &devicePath)
534 {
535 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
536 for (const auto &[deviceId, device] : devices_) {
537 if (device->path == devicePath) {
538 DHLOGI("Device node already registered, node path: %{public}s", device->path.c_str());
539 return true; // device was already registered
540 }
541 }
542 return false;
543 }
544
OpenInputDeviceLocked(const std::string & devicePath)545 int32_t InputHub::OpenInputDeviceLocked(const std::string &devicePath)
546 {
547 if (IsDeviceRegistered(devicePath)) {
548 return DH_SUCCESS;
549 }
550
551 std::lock_guard<std::mutex> my_lock(operationMutex_);
552 DHLOGD("Opening device start: %{public}s", devicePath.c_str());
553 int fd = OpenInputDeviceFdByPath(devicePath);
554 if (fd == UN_INIT_FD_VALUE) {
555 DHLOGE("The fd open failed, devicePath %{public}s.", devicePath.c_str());
556 return ERR_DH_INPUT_HUB_OPEN_DEVICEPATH_FAIL;
557 }
558
559 // Allocate device. (The device object takes ownership of the fd at this point.)
560 std::unique_ptr<Device> device = std::make_unique<Device>(fd, devicePath);
561
562 if (QueryInputDeviceInfo(fd, device) < 0) {
563 CloseFd(fd);
564 return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
565 }
566 GenerateDescriptor(device->identifier);
567 IncreaseLogTimes(device->identifier.descriptor);
568 RecordDeviceLog(devicePath, device->identifier);
569 std::string descriptor = device->identifier.descriptor;
570 if (MakeDevice(fd, std::move(device)) < 0) {
571 CloseFd(fd);
572 if (IsNeedPrintLog(descriptor)) {
573 DHLOGI("Opening device error: %{public}s", devicePath.c_str());
574 }
575 return ERR_DH_INPUT_HUB_MAKE_DEVICE_FAIL;
576 }
577
578 DHLOGI("Opening device finish: %{public}s", devicePath.c_str());
579 return DH_SUCCESS;
580 }
581
RecordSkipDevicePath(std::string path)582 void InputHub::RecordSkipDevicePath(std::string path)
583 {
584 std::lock_guard<std::mutex> lock(skipDevicePathsMutex_);
585 skipDevicePaths_.insert(path);
586 }
587
IsSkipDevicePath(const std::string & path)588 bool InputHub::IsSkipDevicePath(const std::string &path)
589 {
590 std::lock_guard<std::mutex> lock(skipDevicePathsMutex_);
591 return skipDevicePaths_.find(path) != skipDevicePaths_.end();
592 }
593
IncreaseLogTimes(const std::string & dhId)594 void InputHub::IncreaseLogTimes(const std::string& dhId)
595 {
596 if (logTimesMap_.find(dhId) != logTimesMap_.end() && logTimesMap_[dhId] >= INT32_MAX - 1) {
597 logTimesMap_[dhId] = 0;
598 } else {
599 logTimesMap_[dhId]++;
600 }
601 }
602
IsNeedPrintLog(const std::string & dhId) const603 bool InputHub::IsNeedPrintLog(const std::string& dhId) const
604 {
605 return logTimesMap_.find(dhId) == logTimesMap_.end() || logTimesMap_.at(dhId) <= MAX_LOG_TIMES;
606 }
607
QueryInputDeviceInfo(int fd,std::unique_ptr<Device> & device)608 int32_t InputHub::QueryInputDeviceInfo(int fd, std::unique_ptr<Device> &device)
609 {
610 char buffer[INPUT_EVENT_BUFFER_SIZE] = {0};
611 // Get device name.
612 if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
613 DHLOGE("Could not get device name for %{public}s", ConvertErrNo().c_str());
614 } else {
615 buffer[sizeof(buffer) - 1] = '\0';
616 device->identifier.name = buffer;
617 }
618 DHLOGD("QueryInputDeviceInfo deviceName: %{public}s", buffer);
619 // If the device is already a virtual device, don't monitor it.
620 if (device->identifier.name.find(VIRTUAL_DEVICE_NAME) != std::string::npos) {
621 DHLOGE("this is a virtual driver, skip it.");
622 RecordSkipDevicePath(device->path);
623 return ERR_DH_INPUT_HUB_IS_VIRTUAL_DEVICE;
624 }
625 // Get device driver version.
626 int driverVersion;
627 if (ioctl(fd, EVIOCGVERSION, &driverVersion)) {
628 DHLOGE("could not get driver version for %{public}s\n", ConvertErrNo().c_str());
629 RecordSkipDevicePath(device->path);
630 return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
631 }
632 // Get device identifier.
633 struct input_id inputId;
634 if (ioctl(fd, EVIOCGID, &inputId)) {
635 DHLOGE("could not get device input id for %{public}s\n", ConvertErrNo().c_str());
636 RecordSkipDevicePath(device->path);
637 return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
638 }
639 device->identifier.bus = inputId.bustype;
640 device->identifier.product = inputId.product;
641 device->identifier.vendor = inputId.vendor;
642 device->identifier.version = inputId.version;
643 // Get device physical physicalPath.
644 if (ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
645 DHLOGE("could not get physicalPath for %{public}s\n", ConvertErrNo().c_str());
646 } else {
647 buffer[sizeof(buffer) - 1] = '\0';
648 device->identifier.physicalPath = buffer;
649 }
650 // Get device unique id.
651 if (ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
652 DHLOGE("could not get idstring for %{public}s\n", ConvertErrNo().c_str());
653 } else {
654 buffer[sizeof(buffer) - 1] = '\0';
655 device->identifier.uniqueId = buffer;
656 }
657
658 QueryEventInfo(fd, device);
659 return DH_SUCCESS;
660 }
661
QueryEventInfo(int fd,std::unique_ptr<Device> & device)662 void InputHub::QueryEventInfo(int fd, std::unique_ptr<Device> &device)
663 {
664 if (device == nullptr) {
665 DHLOGE("device is nullptr!");
666 return;
667 }
668 if (IsNeedPrintLog(device->identifier.descriptor)) {
669 DHLOGI("QueryEventInfo: devName: %{public}s, dhId: %{public}s!", device->identifier.name.c_str(),
670 GetAnonyString(device->identifier.descriptor).c_str());
671 }
672 struct libevdev *dev = GetLibEvDev(fd);
673 if (dev == nullptr) {
674 if (IsNeedPrintLog(device->identifier.descriptor)) {
675 DHLOGE("dev is nullptr");
676 }
677 return;
678 }
679 GetEventTypes(dev, device->identifier);
680 GetEventKeys(dev, device->identifier);
681 GetABSInfo(dev, device->identifier);
682 GetRELTypes(dev, device->identifier);
683 GetProperties(dev, device->identifier);
684
685 GetMSCBits(fd, device);
686 GetLEDBits(fd, device);
687 GetSwitchBits(fd, device);
688 GetRepeatBits(fd, device);
689
690 libevdev_free(dev);
691 }
692
GetEventMask(int fd,const std::string & eventName,uint32_t type,std::size_t arrayLength,uint8_t * whichBitMask) const693 void InputHub::GetEventMask(int fd, const std::string &eventName, uint32_t type,
694 std::size_t arrayLength, uint8_t *whichBitMask) const
695 {
696 int32_t rc = ioctl(fd, EVIOCGBIT(type, arrayLength), whichBitMask);
697 if (rc < 0) {
698 DHLOGE("Could not get events %{public}s mask: %{public}s", eventName.c_str(), strerror(errno));
699 }
700 }
701
GetMSCBits(int fd,std::unique_ptr<Device> & device)702 void InputHub::GetMSCBits(int fd, std::unique_ptr<Device> &device)
703 {
704 uint8_t mscBitmask[NBYTES(MSC_MAX)] {};
705 GetEventMask(fd, "msc", EV_MSC, sizeof(mscBitmask), mscBitmask);
706
707 for (uint32_t msc = MSC_SERIAL; msc < MSC_MAX; ++msc) {
708 if (TestBit(EV_MSC, device->evBitmask) && TestBit(msc, mscBitmask)) {
709 DHLOGI("Get MSC event: %{public}d", msc);
710 device->identifier.miscellaneous.push_back(msc);
711 }
712 }
713 }
714
GetLEDBits(int fd,std::unique_ptr<Device> & device)715 void InputHub::GetLEDBits(int fd, std::unique_ptr<Device> &device)
716 {
717 uint8_t ledBitmask[NBYTES(LED_MAX)] {};
718 GetEventMask(fd, "led", EV_LED, sizeof(ledBitmask), ledBitmask);
719 for (uint32_t led = LED_NUML; led < LED_MAX; ++led) {
720 if (TestBit(EV_LED, device->evBitmask) && TestBit(led, ledBitmask)) {
721 DHLOGI("Get LED event: %{public}d", led);
722 device->identifier.leds.push_back(led);
723 }
724 }
725 }
726
GetSwitchBits(int fd,std::unique_ptr<Device> & device)727 void InputHub::GetSwitchBits(int fd, std::unique_ptr<Device> &device)
728 {
729 uint8_t switchBitmask[NBYTES(SW_MAX)] {};
730 GetEventMask(fd, "switch", EV_SW, sizeof(switchBitmask), switchBitmask);
731
732 for (uint32_t sw = SW_LID; sw < SW_MAX; ++sw) {
733 if (TestBit(EV_SW, device->evBitmask) && TestBit(sw, switchBitmask)) {
734 DHLOGI("Get Switch event: %{public}d", sw);
735 device->identifier.switchs.push_back(sw);
736 }
737 }
738 }
739
GetRepeatBits(int fd,std::unique_ptr<Device> & device)740 void InputHub::GetRepeatBits(int fd, std::unique_ptr<Device> &device)
741 {
742 uint8_t repBitmask[NBYTES(REP_MAX)] {};
743 GetEventMask(fd, "repeat", EV_REP, sizeof(repBitmask), repBitmask);
744
745 for (uint32_t rep = REP_DELAY; rep < REP_MAX; ++rep) {
746 if (TestBit(EV_REP, device->evBitmask) && TestBit(rep, repBitmask)) {
747 DHLOGI("Get Repeat event: %{public}d", rep);
748 device->identifier.repeats.push_back(rep);
749 }
750 }
751 }
752
GetLibEvDev(int fd)753 struct libevdev* InputHub::GetLibEvDev(int fd)
754 {
755 struct libevdev *dev = nullptr;
756 int rc = 1;
757 rc = libevdev_new_from_fd(fd, &dev);
758 if (rc < 0) {
759 DHLOGE("Failed to init libevdev (%{public}s)", strerror(-rc));
760 return nullptr;
761 }
762 return dev;
763 }
764
GetEventTypes(struct libevdev * dev,InputDevice & identifier)765 void InputHub::GetEventTypes(struct libevdev *dev, InputDevice &identifier)
766 {
767 for (uint32_t eventType = 0; eventType < EV_CNT; eventType++) {
768 if (!libevdev_has_event_type(dev, eventType)) {
769 DHLOGD("The device is not support eventType: %{public}d", eventType);
770 continue;
771 }
772 identifier.eventTypes.push_back(eventType);
773 }
774 }
775
GetEventKeys(struct libevdev * dev,InputDevice & identifier)776 int32_t InputHub::GetEventKeys(struct libevdev *dev, InputDevice &identifier)
777 {
778 if (!libevdev_has_event_type(dev, EV_KEY)) {
779 if (IsNeedPrintLog(identifier.descriptor)) {
780 DHLOGE("The device doesn't has EV_KEY type!");
781 }
782 return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
783 }
784 for (uint32_t eventKey = 0; eventKey < KEY_CNT; eventKey++) {
785 if (!libevdev_has_event_code(dev, EV_KEY, eventKey)) {
786 DHLOGD("The device is not support eventKey: %{public}d", eventKey);
787 continue;
788 }
789 identifier.eventKeys.push_back(eventKey);
790 }
791 return DH_SUCCESS;
792 }
793
GetABSInfo(struct libevdev * dev,InputDevice & identifier)794 int32_t InputHub::GetABSInfo(struct libevdev *dev, InputDevice &identifier)
795 {
796 if (!libevdev_has_event_type(dev, EV_ABS)) {
797 if (IsNeedPrintLog(identifier.descriptor)) {
798 DHLOGE("The device doesn't has EV_ABS type!");
799 }
800 return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
801 }
802 DHLOGI("The device has abs info, devName: %{public}s, dhId: %{public}s!",
803 identifier.name.c_str(), GetAnonyString(identifier.descriptor).c_str());
804 for (uint32_t absType = 0; absType < ABS_CNT; absType++) {
805 if (!libevdev_has_event_code(dev, EV_ABS, absType)) {
806 DHLOGD("The device is not support absType: %{public}d", absType);
807 continue;
808 }
809 identifier.absTypes.push_back(absType);
810 const struct input_absinfo *abs = libevdev_get_abs_info(dev, absType);
811 if (abs == nullptr) {
812 DHLOGE("absInfo is nullptr!");
813 continue;
814 }
815 identifier.absInfos[absType].push_back(abs->value);
816 identifier.absInfos[absType].push_back(abs->minimum);
817 identifier.absInfos[absType].push_back(abs->maximum);
818 identifier.absInfos[absType].push_back(abs->fuzz);
819 identifier.absInfos[absType].push_back(abs->flat);
820 identifier.absInfos[absType].push_back(abs->resolution);
821 }
822 return DH_SUCCESS;
823 }
824
GetRELTypes(struct libevdev * dev,InputDevice & identifier)825 int32_t InputHub::GetRELTypes(struct libevdev *dev, InputDevice &identifier)
826 {
827 if (!libevdev_has_event_type(dev, EV_REL)) {
828 if (IsNeedPrintLog(identifier.descriptor)) {
829 DHLOGE("The device doesn't has EV_REL type!");
830 }
831 return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
832 }
833 for (uint32_t code = 0; code < REL_CNT; code++) {
834 if (!libevdev_has_event_code(dev, EV_REL, code)) {
835 DHLOGD("The device is not support rel code: %{public}d", code);
836 continue;
837 }
838 identifier.relTypes.push_back(code);
839 }
840 return DH_SUCCESS;
841 }
842
GetProperties(struct libevdev * dev,InputDevice & identifier)843 void InputHub::GetProperties(struct libevdev *dev, InputDevice &identifier)
844 {
845 for (uint32_t prop = 0; prop < INPUT_PROP_CNT; prop++) {
846 if (libevdev_has_property(dev, prop)) {
847 DHLOGI("QueryInputDeviceInfo rel prop: %{public}d", prop);
848 identifier.properties.push_back(prop);
849 }
850 }
851 }
852
MakeDevice(int fd,std::unique_ptr<Device> device)853 int32_t InputHub::MakeDevice(int fd, std::unique_ptr<Device> device)
854 {
855 // See if this is a multi-touch touchscreen device.
856 if (TestBit(BTN_TOUCH, device->keyBitmask) &&
857 TestBit(ABS_MT_POSITION_X, device->absBitmask) &&
858 TestBit(ABS_MT_POSITION_Y, device->absBitmask)) {
859 QueryLocalTouchScreenInfo(fd, device);
860 device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
861 } else if (TestBit(BTN_TOUCH, device->keyBitmask) &&
862 TestBit(ABS_X, device->absBitmask) &&
863 TestBit(ABS_Y, device->absBitmask)) {
864 QueryLocalTouchScreenInfo(fd, device);
865 device->classes |= INPUT_DEVICE_CLASS_TOUCH;
866 }
867
868 // See if this is a cursor device such as a trackball or mouse.
869 if (TestBit(BTN_MOUSE, device->keyBitmask)
870 && TestBit(REL_X, device->relBitmask)
871 && TestBit(REL_Y, device->relBitmask)) {
872 device->classes |= INPUT_DEVICE_CLASS_CURSOR;
873 }
874
875 // for Linux version 4.14.116, touchpad recognized as mouse and keyboard at same time,
876 // need to avoid device->classes to be 0x09, which mmi can't handler.
877 // See if this is a keyboard.
878 if (device->classes == 0) {
879 bool haveKeyboardKeys = ContainsNonZeroByte(device->keyBitmask, 0, SizeofBitArray(BTN_MISC));
880 if (haveKeyboardKeys) {
881 device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
882 }
883 }
884
885 // If the device isn't recognized as something we handle, don't monitor it.
886 if (device->classes == 0) {
887 if (IsNeedPrintLog(device->identifier.descriptor)) {
888 DHLOGI("Dropping device: name='%{public}s'", device->identifier.name.c_str());
889 }
890 return ERR_DH_INPUT_HUB_MAKE_DEVICE_FAIL;
891 }
892
893 if (RegisterDeviceForEpollLocked(*device) != DH_SUCCESS) {
894 return ERR_DH_INPUT_HUB_MAKE_DEVICE_FAIL;
895 }
896
897 device->identifier.classes = device->classes;
898
899 DHLOGI("inputType=%{public}d", inputTypes_.load());
900 DHLOGI("New device: fd=%{public}d, name='%{public}s', classes=0x%{public}x", fd, device->identifier.name.c_str(),
901 device->classes);
902
903 AddDeviceLocked(std::move(device));
904 return DH_SUCCESS;
905 }
906
QueryLocalTouchScreenInfo(int fd,std::unique_ptr<Device> & device)907 int32_t InputHub::QueryLocalTouchScreenInfo(int fd, std::unique_ptr<Device> &device)
908 {
909 LocalTouchScreenInfo info = DInputContext::GetInstance().GetLocalTouchScreenInfo();
910 device->identifier.classes |= INPUT_DEVICE_CLASS_TOUCH_MT;
911 info.localAbsInfo.deviceInfo = device->identifier;
912
913 struct input_absinfo absInfo;
914 ioctl(fd, EVIOCGABS(ABS_MT_POSITION_X), &absInfo);
915 info.localAbsInfo.absXMin = absInfo.minimum;
916 info.localAbsInfo.absXMax = absInfo.maximum;
917 info.localAbsInfo.absMtPositionXMin = absInfo.minimum;
918 info.localAbsInfo.absMtPositionXMax = absInfo.maximum;
919 info.sinkPhyWidth = static_cast<uint32_t>(absInfo.maximum + 1);
920
921 ioctl(fd, EVIOCGABS(ABS_MT_POSITION_Y), &absInfo);
922 info.localAbsInfo.absYMin = absInfo.minimum;
923 info.localAbsInfo.absYMax = absInfo.maximum;
924 info.localAbsInfo.absMtPositionYMin = absInfo.minimum;
925 info.localAbsInfo.absMtPositionYMax = absInfo.maximum;
926 info.sinkPhyHeight = static_cast<uint32_t>(absInfo.maximum + 1);
927
928 ioctl(fd, EVIOCGABS(ABS_PRESSURE), &absInfo);
929 info.localAbsInfo.absPressureMin = absInfo.minimum;
930 info.localAbsInfo.absPressureMax = absInfo.maximum;
931 info.localAbsInfo.absMtPressureMin = absInfo.minimum;
932 info.localAbsInfo.absMtPressureMax = absInfo.maximum;
933
934 ioctl(fd, EVIOCGABS(ABS_MT_TOUCH_MAJOR), &absInfo);
935 info.localAbsInfo.absMtTouchMajorMin = absInfo.minimum;
936 info.localAbsInfo.absMtTouchMajorMax = absInfo.maximum;
937
938 ioctl(fd, EVIOCGABS(ABS_MT_TOUCH_MINOR), &absInfo);
939 info.localAbsInfo.absMtTouchMinorMin = absInfo.minimum;
940 info.localAbsInfo.absMtTouchMinorMax = absInfo.maximum;
941
942 ioctl(fd, EVIOCGABS(ABS_MT_ORIENTATION), &absInfo);
943 info.localAbsInfo.absMtOrientationMin = absInfo.minimum;
944 info.localAbsInfo.absMtOrientationMax = absInfo.maximum;
945
946 ioctl(fd, EVIOCGABS(ABS_MT_BLOB_ID), &absInfo);
947 info.localAbsInfo.absMtBlobIdMin = absInfo.minimum;
948 info.localAbsInfo.absMtBlobIdMax = absInfo.maximum;
949
950 ioctl(fd, EVIOCGABS(ABS_MT_TRACKING_ID), &absInfo);
951 info.localAbsInfo.absMtTrackingIdMin = absInfo.minimum;
952 info.localAbsInfo.absMtTrackingIdMax = absInfo.maximum;
953
954 DInputContext::GetInstance().SetLocalTouchScreenInfo(info);
955 return DH_SUCCESS;
956 }
957
StringPrintf(const char * format,...) const958 std::string InputHub::StringPrintf(const char *format, ...) const
959 {
960 char space[SPACELENGTH] = {0};
961 va_list ap;
962 va_start(ap, format);
963 std::string result;
964 int32_t ret = vsnprintf_s(space, sizeof(space), sizeof(space) - 1, format, ap);
965 if (ret >= DH_SUCCESS && static_cast<size_t>(ret) < sizeof(space)) {
966 result = space;
967 } else {
968 va_end(ap);
969 return "the buffer is overflow!";
970 }
971 va_end(ap);
972 return result;
973 }
974
GenerateDescriptor(InputDevice & identifier) const975 void InputHub::GenerateDescriptor(InputDevice &identifier) const
976 {
977 std::string rawDescriptor;
978 rawDescriptor += StringPrintf(":%04x:%04x:", identifier.vendor,
979 identifier.product);
980 // add handling for USB devices to not uniqueify kbs that show up twice
981 if (!identifier.uniqueId.empty()) {
982 rawDescriptor += "uniqueId:";
983 rawDescriptor += identifier.uniqueId;
984 }
985 if (!identifier.physicalPath.empty()) {
986 rawDescriptor += "physicalPath:";
987 rawDescriptor += identifier.physicalPath;
988 }
989 if (!identifier.name.empty()) {
990 rawDescriptor += "name:";
991 std::string name = identifier.name;
992 rawDescriptor += regex_replace(name, std::regex(" "), "");
993 }
994
995 identifier.descriptor = DH_ID_PREFIX + Sha256(rawDescriptor);
996 if (IsNeedPrintLog(identifier.descriptor)) {
997 DHLOGI("Created descriptor: raw=%{public}s, cooked=%{public}s", rawDescriptor.c_str(),
998 GetAnonyString(identifier.descriptor).c_str());
999 }
1000 }
1001
RegisterDeviceForEpollLocked(const Device & device)1002 int32_t InputHub::RegisterDeviceForEpollLocked(const Device &device)
1003 {
1004 int32_t result = RegisterFdForEpoll(device.fd);
1005 if (result != DH_SUCCESS) {
1006 DHLOGE("Could not add input device fd to epoll for device, path: %{public}s", device.path.c_str());
1007 return result;
1008 }
1009 return result;
1010 }
1011
RegisterFdForEpoll(int fd)1012 int32_t InputHub::RegisterFdForEpoll(int fd)
1013 {
1014 struct epoll_event eventItem = {};
1015 eventItem.events = EPOLLIN | EPOLLWAKEUP;
1016 eventItem.data.fd = fd;
1017 if (epoll_ctl(epollFd_, EPOLL_CTL_ADD, fd, &eventItem)) {
1018 DHLOGE("Could not add fd to epoll instance: %{public}s", ConvertErrNo().c_str());
1019 return -errno;
1020 }
1021 return DH_SUCCESS;
1022 }
1023
AddDeviceLocked(std::unique_ptr<Device> device)1024 void InputHub::AddDeviceLocked(std::unique_ptr<Device> device)
1025 {
1026 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1027 openingDevices_.push_back(std::move(device));
1028 }
1029
CloseDeviceLocked(Device & device)1030 void InputHub::CloseDeviceLocked(Device &device)
1031 {
1032 DHLOGI("Removed device: path=%{public}s name=%{public}s fd=%{public}d classes=0x%{public}x",
1033 device.path.c_str(), device.identifier.name.c_str(), device.fd, device.classes);
1034
1035 UnregisterDeviceFromEpollLocked(device);
1036 device.Close();
1037 {
1038 std::lock_guard<std::mutex> devicesLock(devicesMutex_);
1039 closingDevices_.push_back(std::move(devices_[device.path]));
1040 devices_.erase(device.path);
1041 }
1042 }
1043
CloseDeviceForAllLocked(Device & device)1044 void InputHub::CloseDeviceForAllLocked(Device &device)
1045 {
1046 DHLOGI("Removed device: path=%{public}s name=%{public}s fd=%{public}d classes=0x%{public}x",
1047 device.path.c_str(), device.identifier.name.c_str(), device.fd, device.classes);
1048
1049 UnregisterDeviceFromEpollLocked(device);
1050 device.Close();
1051 closingDevices_.push_back(std::move(devices_[device.path]));
1052 devices_.erase(device.path);
1053 }
1054
UnregisterDeviceFromEpollLocked(const Device & device) const1055 int32_t InputHub::UnregisterDeviceFromEpollLocked(const Device &device) const
1056 {
1057 if (device.HasValidFd()) {
1058 int32_t result = UnregisterFdFromEpoll(device.fd);
1059 if (result != DH_SUCCESS) {
1060 DHLOGE("Could not remove input device fd from epoll for device, path: %{public}s", device.path.c_str());
1061 return result;
1062 }
1063 }
1064 return DH_SUCCESS;
1065 }
1066
UnregisterFdFromEpoll(int fd) const1067 int32_t InputHub::UnregisterFdFromEpoll(int fd) const
1068 {
1069 if (epoll_ctl(epollFd_, EPOLL_CTL_DEL, fd, nullptr)) {
1070 DHLOGE("Could not remove fd from epoll instance: %{public}s", ConvertErrNo().c_str());
1071 return ERR_DH_INPUT_HUB_UNREGISTER_FD_FAIL;
1072 }
1073 return DH_SUCCESS;
1074 }
1075
ReadNotifyLocked()1076 int32_t InputHub::ReadNotifyLocked()
1077 {
1078 size_t res;
1079 char eventBuf[EVENT_BUFFER_MAX] = {0};
1080 struct inotify_event *event;
1081
1082 DHLOGI("readNotify nfd: %{public}d\n", iNotifyFd_);
1083 res = static_cast<size_t>(read(iNotifyFd_, eventBuf, sizeof(eventBuf)));
1084 if (res < sizeof(*event)) {
1085 if (errno == EINTR) {
1086 return DH_SUCCESS;
1087 }
1088 DHLOGE("could not get event, %{public}s\n", ConvertErrNo().c_str());
1089 return ERR_DH_INPUT_HUB_GET_EVENT_FAIL;
1090 }
1091
1092 {
1093 size_t eventSize = 0;
1094 size_t eventPos = 0;
1095 while (res >= sizeof(*event) && eventPos < static_cast<size_t>(EVENT_BUFFER_MAX)) {
1096 event = reinterpret_cast<struct inotify_event *>(eventBuf + eventPos);
1097 JudgeDeviceOpenOrClose(*event);
1098 eventSize = sizeof(*event) + event->len;
1099 res -= eventSize;
1100 eventPos += eventSize;
1101 }
1102 }
1103 return DH_SUCCESS;
1104 }
1105
JudgeDeviceOpenOrClose(const inotify_event & event)1106 void InputHub::JudgeDeviceOpenOrClose(const inotify_event &event)
1107 {
1108 if (event.len) {
1109 if (event.wd == inputWd_) {
1110 std::string filename = std::string(DEVICE_PATH) + "/" + event.name;
1111 if (event.mask & IN_CREATE) {
1112 OpenInputDeviceLocked(filename);
1113 } else {
1114 DHLOGI("Removing device '%{public}s' due to inotify event\n", filename.c_str());
1115 CloseDeviceByPathLocked(filename);
1116 }
1117 } else {
1118 DHLOGI("Unexpected inotify event, wd = %i", event.wd);
1119 }
1120 }
1121 }
1122
CloseDeviceByPathLocked(const std::string & devicePath)1123 void InputHub::CloseDeviceByPathLocked(const std::string &devicePath)
1124 {
1125 Device* device = GetDeviceByPathLocked(devicePath);
1126 if (device) {
1127 CloseDeviceLocked(*device);
1128 return;
1129 }
1130 DHLOGI("Remove device: %{public}s not found, device may already have been removed.", devicePath.c_str());
1131 }
1132
CloseAllDevicesLocked()1133 void InputHub::CloseAllDevicesLocked()
1134 {
1135 DHLOGI("Close All Devices");
1136 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1137 while (!devices_.empty()) {
1138 CloseDeviceForAllLocked(*(devices_.begin()->second));
1139 }
1140 }
1141
GetDeviceByPathLocked(const std::string & devicePath)1142 InputHub::Device* InputHub::GetDeviceByPathLocked(const std::string &devicePath)
1143 {
1144 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1145 for (const auto &[id, device] : devices_) {
1146 if (device->path == devicePath) {
1147 return device.get();
1148 }
1149 }
1150 return nullptr;
1151 }
1152
GetDeviceByFdLocked(int fd)1153 InputHub::Device* InputHub::GetDeviceByFdLocked(int fd)
1154 {
1155 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1156 for (const auto &[id, device] : devices_) {
1157 if (device->fd == fd) {
1158 return device.get();
1159 }
1160 }
1161 return nullptr;
1162 }
1163
GetSupportDeviceByFd(int fd)1164 InputHub::Device* InputHub::GetSupportDeviceByFd(int fd)
1165 {
1166 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1167 for (const auto &[id, device] : devices_) {
1168 if (device != nullptr && device->fd == fd) {
1169 return device.get();
1170 }
1171 }
1172 return nullptr;
1173 }
1174
ContainsNonZeroByte(const uint8_t * array,uint32_t startIndex,uint32_t endIndex)1175 bool InputHub::ContainsNonZeroByte(const uint8_t *array, uint32_t startIndex, uint32_t endIndex)
1176 {
1177 const uint8_t* end = array + endIndex;
1178 array += startIndex;
1179 while (array != end) {
1180 if (*(array++) != 0) {
1181 return true;
1182 }
1183 }
1184 return false;
1185 }
1186
ProcessEventTimestamp(const input_event & event)1187 int64_t InputHub::ProcessEventTimestamp(const input_event &event)
1188 {
1189 const int64_t inputEventTime = event.input_event_sec * 1000000000LL + event.input_event_usec * 1000LL;
1190 return inputEventTime;
1191 }
1192
TestBit(uint32_t bit,const uint8_t * array)1193 bool InputHub::TestBit(uint32_t bit, const uint8_t *array)
1194 {
1195 constexpr int units = 8;
1196 return (array)[(bit) / units] & (1 << ((bit) % units));
1197 }
1198
SizeofBitArray(uint32_t bit)1199 uint32_t InputHub::SizeofBitArray(uint32_t bit)
1200 {
1201 constexpr int round = 7;
1202 constexpr int divisor = 8;
1203 return ((bit) + round) / divisor;
1204 }
1205
SaveAffectDhId(bool isEnable,const std::string & dhId,AffectDhIds & affDhIds)1206 void InputHub::SaveAffectDhId(bool isEnable, const std::string &dhId, AffectDhIds &affDhIds)
1207 {
1208 if (isEnable) {
1209 affDhIds.sharingDhIds.push_back(dhId);
1210 } else {
1211 affDhIds.noSharingDhIds.push_back(dhId);
1212 }
1213 }
1214
SetSupportInputType(bool enabled,const uint32_t & inputTypes)1215 AffectDhIds InputHub::SetSupportInputType(bool enabled, const uint32_t &inputTypes)
1216 {
1217 AffectDhIds affDhIds;
1218 inputTypes_ = inputTypes;
1219 DHLOGI("SetSupportInputType: inputTypes=0x%x,", inputTypes_.load());
1220 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1221 for (const auto &[id, device] : devices_) {
1222 if (device->classes & inputTypes_) {
1223 device->isShare = enabled;
1224 DHLOGW("ByType dhid:%{public}s, isshare:%{public}d",
1225 GetAnonyString(device->identifier.descriptor).c_str(), enabled);
1226 SaveAffectDhId(enabled, device->identifier.descriptor, affDhIds);
1227 }
1228 }
1229
1230 return affDhIds;
1231 }
1232
SetSharingDevices(bool enabled,std::vector<std::string> dhIds)1233 AffectDhIds InputHub::SetSharingDevices(bool enabled, std::vector<std::string> dhIds)
1234 {
1235 AffectDhIds affDhIds;
1236 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1237 DHLOGI("SetSharingDevices start");
1238 for (auto dhId : dhIds) {
1239 DHLOGI("SetSharingDevices dhId: %{public}s, size: %{public}zu, enabled: %{public}d",
1240 GetAnonyString(dhId).c_str(), devices_.size(), enabled);
1241 sharedDHIds_[dhId] = enabled;
1242 for (const auto &[id, device] : devices_) {
1243 DHLOGI("deviceName %{public}s ,dhId: %{public}s ", device->identifier.name.c_str(),
1244 GetAnonyString(device->identifier.descriptor).c_str());
1245 if (device->identifier.descriptor == dhId) {
1246 device->isShare = enabled;
1247 DHLOGW("dhid:%{public}s, isshare:%{public}d",
1248 GetAnonyString(device->identifier.descriptor).c_str(), enabled);
1249 SaveAffectDhId(enabled, device->identifier.descriptor, affDhIds);
1250 break;
1251 }
1252 }
1253 }
1254 DHLOGI("SetSharingDevices end");
1255 return affDhIds;
1256 }
1257
GetSharingDevices()1258 std::vector<std::string> InputHub::GetSharingDevices()
1259 {
1260 std::vector<std::string> sharingDevices;
1261 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1262 for (const auto &[id, device] : devices_) {
1263 if (device->isShare) {
1264 DHLOGI("Find sharing dhid: %{public}s", GetAnonyString(device->identifier.descriptor).c_str());
1265 sharingDevices.push_back(device->identifier.descriptor);
1266 }
1267 }
1268 return sharingDevices;
1269 }
1270
GetSharedMousePathByDhId(const std::vector<std::string> & dhIds,std::string & sharedMousePath,std::string & sharedMouseDhId)1271 void InputHub::GetSharedMousePathByDhId(const std::vector<std::string> &dhIds, std::string &sharedMousePath,
1272 std::string &sharedMouseDhId)
1273 {
1274 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1275 DHLOGI("GetSharedMousePathByDhId: devices_.size:%{public}zu,", devices_.size());
1276 for (const auto &dhId : dhIds) {
1277 for (const auto &[id, device] : devices_) {
1278 if (device == nullptr) {
1279 DHLOGE("device is nullptr");
1280 continue;
1281 }
1282 DHLOGI("descriptor:%{public}s, isShare[%{public}d], type[%{public}d]",
1283 GetAnonyString(device->identifier.descriptor).c_str(), device->isShare, device->classes);
1284 if ((device->identifier.descriptor == dhId) && ((device->classes & INPUT_DEVICE_CLASS_CURSOR) != 0 ||
1285 (device->classes & INPUT_DEVICE_CLASS_TOUCH) != 0 ||
1286 ((device->classes & INPUT_DEVICE_CLASS_TOUCH_MT) != 0 && IsTouchPad(device->identifier)))) {
1287 sharedMouseDhId = dhId;
1288 sharedMousePath = device->path;
1289 return; // return First shared mouse
1290 }
1291 }
1292 }
1293 }
1294
GetSharedKeyboardPathsByDhIds(const std::vector<std::string> & dhIds,std::vector<std::string> & sharedKeyboardPaths,std::vector<std::string> & sharedKeyboardDhIds)1295 void InputHub::GetSharedKeyboardPathsByDhIds(const std::vector<std::string> &dhIds,
1296 std::vector<std::string> &sharedKeyboardPaths, std::vector<std::string> &sharedKeyboardDhIds)
1297 {
1298 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1299 DHLOGI("GetSharedKeyboardPathsByDhIds: devices_.size:%{public}zu,", devices_.size());
1300 for (const auto &dhId : dhIds) {
1301 for (const auto &[id, device] : devices_) {
1302 if (device == nullptr) {
1303 DHLOGE("device is nullptr");
1304 continue;
1305 }
1306 DHLOGI("descriptor:%{public}s, isShare[%{public}d], type[%{public}d]",
1307 GetAnonyString(device->identifier.descriptor).c_str(), device->isShare, device->classes);
1308 if ((device->identifier.descriptor == dhId) &&
1309 ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0)) {
1310 sharedKeyboardDhIds.push_back(dhId);
1311 sharedKeyboardPaths.push_back(device->path);
1312 }
1313 }
1314 }
1315 }
1316
GetDevicesInfoByType(const uint32_t inputTypes,std::map<int32_t,std::string> & datas)1317 void InputHub::GetDevicesInfoByType(const uint32_t inputTypes, std::map<int32_t, std::string> &datas)
1318 {
1319 uint32_t dhType = 0;
1320
1321 if ((inputTypes & static_cast<uint32_t>(DInputDeviceType::MOUSE)) != 0) {
1322 dhType |= INPUT_DEVICE_CLASS_CURSOR;
1323 }
1324
1325 if ((inputTypes & static_cast<uint32_t>(DInputDeviceType::KEYBOARD)) != 0) {
1326 dhType |= INPUT_DEVICE_CLASS_KEYBOARD;
1327 }
1328
1329 if ((inputTypes & static_cast<uint32_t>(DInputDeviceType::TOUCHSCREEN)) != 0) {
1330 dhType |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
1331 }
1332
1333 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1334 for (const auto &[id, device] : devices_) {
1335 if (device->classes & dhType) {
1336 datas.insert(std::pair<int32_t, std::string>(device->fd, device->identifier.descriptor));
1337 }
1338 }
1339 }
1340
GetDevicesInfoByDhId(std::vector<std::string> dhidsVec,std::map<int32_t,std::string> & datas)1341 void InputHub::GetDevicesInfoByDhId(std::vector<std::string> dhidsVec, std::map<int32_t, std::string> &datas)
1342 {
1343 for (auto dhId : dhidsVec) {
1344 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1345 for (const auto &[id, device] : devices_) {
1346 if (device->identifier.descriptor == dhId) {
1347 datas.insert(std::pair<int32_t, std::string>(device->fd, dhId));
1348 }
1349 }
1350 }
1351 }
1352
IsAllDevicesStoped()1353 bool InputHub::IsAllDevicesStoped()
1354 {
1355 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1356 for (const auto &[dhId, isShared] : sharedDHIds_) {
1357 DHLOGI("the dhId: %{public}s, isShared: %{public}d", GetAnonyString(dhId).c_str(), isShared);
1358 if (isShared) {
1359 return false;
1360 }
1361 }
1362 return true;
1363 }
1364
RecordDeviceLog(const std::string & devicePath,const InputDevice & identifier)1365 void InputHub::RecordDeviceLog(const std::string &devicePath, const InputDevice &identifier)
1366 {
1367 if (IsNeedPrintLog(identifier.descriptor)) {
1368 DHLOGI("add device: %{public}s\n", devicePath.c_str());
1369 DHLOGI(" bus: %{public}04x\n"
1370 " vendor %{public}04x\n"
1371 " product %{public}04x\n"
1372 " version %{public}04x\n",
1373 identifier.bus, identifier.vendor, identifier.product, identifier.version);
1374 DHLOGI(" name: \"%{public}s\"\n", identifier.name.c_str());
1375 DHLOGI(" physicalPath: \"%{public}s\"\n", identifier.physicalPath.c_str());
1376 DHLOGI(" unique id: \"%{public}s\"\n", identifier.uniqueId.c_str());
1377 DHLOGI(" descriptor: \"%{public}s\"\n", GetAnonyString(identifier.descriptor).c_str());
1378 }
1379 }
1380
RecordChangeEventLog(const RawEvent & event)1381 void InputHub::RecordChangeEventLog(const RawEvent &event)
1382 {
1383 std::string eventType = "";
1384 switch (event.type) {
1385 case EV_KEY:
1386 eventType = "EV_KEY";
1387 break;
1388 case EV_REL:
1389 eventType = "EV_REL";
1390 break;
1391 case EV_ABS:
1392 eventType = "EV_ABS";
1393 break;
1394 case EV_SYN:
1395 eventType = "EV_SYN";
1396 break;
1397 default:
1398 eventType = "other type " + std::to_string(event.type);
1399 break;
1400 }
1401 DHLOGI("0.E2E-Test Sink collect change event, EventType: %{public}s, Code: %{public}d, Value: %{public}d, "
1402 "Path: %{public}s, descriptor: %{public}s, When: %{public}" PRId64 "", eventType.c_str(), event.code,
1403 event.value, event.path.c_str(), GetAnonyString(event.descriptor).c_str(), event.when);
1404 }
1405
RecordEventLog(const RawEvent * event)1406 void InputHub::RecordEventLog(const RawEvent *event)
1407 {
1408 std::string eventType = "";
1409 switch (event->type) {
1410 case EV_KEY:
1411 eventType = "EV_KEY";
1412 break;
1413 case EV_REL:
1414 eventType = "EV_REL";
1415 break;
1416 case EV_ABS:
1417 eventType = "EV_ABS";
1418 break;
1419 case EV_SYN:
1420 eventType = "EV_SYN";
1421 break;
1422 default:
1423 eventType = "other type " + std::to_string(event->type);
1424 break;
1425 }
1426 DHLOGD("1.E2E-Test Sink collect event, EventType: %{public}s, Code: %{public}d, Value: %{public}d, "
1427 "Path: %{public}s, descriptor: %{public}s, When: %{public}" PRId64 "", eventType.c_str(), event->code,
1428 event->value, event->path.c_str(), GetAnonyString(event->descriptor).c_str(), event->when);
1429 }
1430
HandleTouchScreenEvent(struct input_event readBuffer[],const size_t count,std::vector<bool> & needFilted)1431 void InputHub::HandleTouchScreenEvent(struct input_event readBuffer[], const size_t count,
1432 std::vector<bool> &needFilted)
1433 {
1434 std::vector<std::pair<size_t, size_t>> absIndexs;
1435 int32_t firstIndex = -1;
1436 int32_t lastIndex = -1;
1437
1438 for (size_t i = 0; i < count; i++) {
1439 struct input_event& iev = readBuffer[i];
1440 if ((iev.type == EV_ABS) && (iev.code == ABS_X || iev.code == ABS_MT_POSITION_X)) {
1441 firstIndex = static_cast<int32_t>(i);
1442 } else if (iev.type == EV_SYN) {
1443 lastIndex = static_cast<int32_t>(i);
1444 }
1445 if ((firstIndex >= 0) && (lastIndex > firstIndex)) {
1446 absIndexs.emplace_back(std::make_pair((size_t)firstIndex, (size_t)lastIndex));
1447 }
1448 }
1449
1450 AbsInfo absInfo = {
1451 .absX = 0,
1452 .absY = 0,
1453 .absXIndex = -1,
1454 .absYIndex = -1,
1455 };
1456 for (auto iter : absIndexs) {
1457 absInfo.absXIndex = -1;
1458 absInfo.absYIndex = -1;
1459
1460 for (size_t j = iter.first; j <= iter.second; j++) {
1461 struct input_event &iev = readBuffer[j];
1462 if (iev.code == ABS_X || iev.code == ABS_MT_POSITION_X) {
1463 absInfo.absX = static_cast<uint32_t>(iev.value);
1464 absInfo.absXIndex = static_cast<int32_t>(j);
1465 }
1466 if (iev.code == ABS_Y || iev.code == ABS_MT_POSITION_Y) {
1467 absInfo.absY = static_cast<uint32_t>(iev.value);
1468 absInfo.absYIndex = static_cast<int32_t>(j);
1469 }
1470 }
1471
1472 if ((absInfo.absXIndex < 0) || (absInfo.absYIndex < 0)) {
1473 for (size_t j = iter.first; j <= iter.second; j++) {
1474 needFilted[j] = true;
1475 }
1476 continue;
1477 }
1478 if (!CheckTouchPointRegion(readBuffer, absInfo)) {
1479 for (size_t j = iter.first; j <= iter.second; j++) {
1480 needFilted[j] = true;
1481 }
1482 }
1483 }
1484 }
1485
CheckTouchPointRegion(struct input_event readBuffer[],const AbsInfo & absInfo)1486 bool InputHub::CheckTouchPointRegion(struct input_event readBuffer[], const AbsInfo &absInfo)
1487 {
1488 auto sinkInfos = DInputContext::GetInstance().GetAllSinkScreenInfo();
1489
1490 for (const auto &[id, sinkInfo] : sinkInfos) {
1491 auto info = sinkInfo.transformInfo;
1492 if ((absInfo.absX >= info.sinkWinPhyX) && (absInfo.absX <= (info.sinkWinPhyX + info.sinkProjPhyWidth))
1493 && (absInfo.absY >= info.sinkWinPhyY) && (absInfo.absY <= (info.sinkWinPhyY + info.sinkProjPhyHeight))) {
1494 touchDescriptor = sinkInfo.srcScreenInfo.sourcePhyId;
1495 readBuffer[absInfo.absXIndex].value = (absInfo.absX - info.sinkWinPhyX) * info.coeffWidth;
1496 readBuffer[absInfo.absYIndex].value = (absInfo.absY - info.sinkWinPhyY) * info.coeffHeight;
1497 return true;
1498 }
1499 }
1500 return false;
1501 }
1502
CollectTargetDevices()1503 std::vector<InputHub::Device*> InputHub::CollectTargetDevices()
1504 {
1505 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1506 std::vector<InputHub::Device*> tarVec;
1507 for (const auto &dev : devices_) {
1508 if (((dev.second->classes & INPUT_DEVICE_CLASS_TOUCH) != 0) ||
1509 ((dev.second->classes & INPUT_DEVICE_CLASS_TOUCH_MT) != 0) ||
1510 ((dev.second->classes & INPUT_DEVICE_CLASS_CURSOR) != 0) ||
1511 ((dev.second->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0)) {
1512 DHLOGI("Find target devs need check stat, path: %{public}s, name: %{public}s",
1513 dev.first.c_str(), dev.second->identifier.name.c_str());
1514 tarVec.push_back(dev.second.get());
1515 }
1516 }
1517
1518 return tarVec;
1519 }
1520
SavePressedKeyState(const InputHub::Device * dev,int32_t keyCode)1521 void InputHub::SavePressedKeyState(const InputHub::Device *dev, int32_t keyCode)
1522 {
1523 struct RawEvent event = {
1524 .type = EV_KEY,
1525 .code = keyCode,
1526 .value = KEY_DOWN_STATE,
1527 .descriptor = dev->identifier.descriptor,
1528 .path = dev->path
1529 };
1530 DInputSinkState::GetInstance().AddKeyDownState(event);
1531 DHLOGI("Find Pressed key: %{public}d, device path: %{public}s, dhId: %{public}s", keyCode, dev->path.c_str(),
1532 GetAnonyString(dev->identifier.descriptor).c_str());
1533 }
1534
IsLengthExceeds(const unsigned long * keyState,const unsigned long len,int keyIndex)1535 bool InputHub::IsLengthExceeds(const unsigned long *keyState, const unsigned long len, int keyIndex)
1536 {
1537 if (len < (keyIndex / LONG_BITS) + 1) {
1538 DHLOGE("Length exceeds for key index: %{public}d", keyIndex);
1539 return true;
1540 }
1541 return false;
1542 }
1543
CheckTargetKeyState(const InputHub::Device * dev,const unsigned long * keyState,const unsigned long len)1544 void InputHub::CheckTargetKeyState(const InputHub::Device *dev, const unsigned long *keyState, const unsigned long len)
1545 {
1546 // If device is a mouse, record the mouse pressed key.
1547 if ((dev->classes & INPUT_DEVICE_CLASS_CURSOR) != 0) {
1548 if (IsLengthExceeds(keyState, len, BTN_LEFT)) {
1549 return;
1550 }
1551 int mouseLeftBtnState = BitIsSet(keyState, BTN_LEFT);
1552 if (mouseLeftBtnState != 0) {
1553 SavePressedKeyState(dev, BTN_LEFT);
1554 }
1555 if (IsLengthExceeds(keyState, len, BTN_RIGHT)) {
1556 return;
1557 }
1558 int mouseRightBtnState = BitIsSet(keyState, BTN_RIGHT);
1559 if (mouseRightBtnState != 0) {
1560 SavePressedKeyState(dev, BTN_RIGHT);
1561 }
1562 if (IsLengthExceeds(keyState, len, BTN_MIDDLE)) {
1563 return;
1564 }
1565 int mouseMidBtnState = BitIsSet(keyState, BTN_MIDDLE);
1566 if (mouseMidBtnState != 0) {
1567 SavePressedKeyState(dev, BTN_MIDDLE);
1568 }
1569 }
1570
1571 // If device is a keyboard, record all the pressed keys.
1572 if ((dev->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) {
1573 for (int32_t keyIndex = 0; keyIndex < KEY_MAX; keyIndex++) {
1574 if (IsLengthExceeds(keyState, len, keyIndex)) {
1575 return;
1576 }
1577 if (BitIsSet(keyState, keyIndex) != 0) {
1578 SavePressedKeyState(dev, keyIndex);
1579 }
1580 }
1581 }
1582
1583 // If device is a touchscreen or touchpad, record the touch event.
1584 if ((dev->classes & INPUT_DEVICE_CLASS_TOUCH) != 0 || (dev->classes & INPUT_DEVICE_CLASS_TOUCH_MT) != 0) {
1585 if (IsLengthExceeds(keyState, len, BTN_TOUCH)) {
1586 return;
1587 }
1588 int btnTouchState = BitIsSet(keyState, BTN_TOUCH);
1589 if (btnTouchState != 0) {
1590 SavePressedKeyState(dev, BTN_TOUCH);
1591 }
1592 }
1593 }
1594
1595
CheckTargetDevicesState(std::vector<InputHub::Device * > targetDevices)1596 void InputHub::CheckTargetDevicesState(std::vector<InputHub::Device*> targetDevices)
1597 {
1598 uint32_t count = 0;
1599 unsigned long keyState[NLONGS(KEY_CNT)] = { 0 };
1600 for (const auto *dev : targetDevices) {
1601 while (true) {
1602 if (count > READ_RETRY_MAX) {
1603 break;
1604 }
1605 // Query all key state
1606 int rc = ioctl(dev->fd, EVIOCGKEY(sizeof(keyState)), keyState);
1607 if (rc < 0) {
1608 DHLOGE("read all key state failed, rc=%{public}d", rc);
1609 count += 1;
1610 std::this_thread::sleep_for(std::chrono::milliseconds(READ_SLEEP_TIME_MS));
1611 continue;
1612 }
1613 CheckTargetKeyState(dev, keyState, NLONGS(KEY_CNT));
1614 break;
1615 }
1616 }
1617 }
1618
RecordDeviceStates()1619 void InputHub::RecordDeviceStates()
1620 {
1621 DHLOGI("Start Record keys states");
1622 ScanAndRecordInputDevices();
1623 std::vector<InputHub::Device*> tarDevices = CollectTargetDevices();
1624 DHLOGI("Check target states device num: %{public}zu", tarDevices.size());
1625 CheckTargetDevicesState(tarDevices);
1626 DHLOGI("Finish Record Keys states");
1627 }
1628
ClearDeviceStates()1629 void InputHub::ClearDeviceStates()
1630 {
1631 DHLOGI("Clear Device state");
1632 DInputSinkState::GetInstance().ClearDeviceStates();
1633 }
1634
ClearSkipDevicePaths()1635 void InputHub::ClearSkipDevicePaths()
1636 {
1637 DHLOGI("Clear Skip device path");
1638 std::lock_guard<std::mutex> lock(skipDevicePathsMutex_);
1639 skipDevicePaths_.clear();
1640 }
1641
Device(int fd,const std::string & path)1642 InputHub::Device::Device(int fd, const std::string &path)
1643 : next(nullptr), fd(fd), path(path), identifier({}), classes(0), enabled(false),
1644 isShare(false), isVirtual(fd < 0) {
1645 // Figure out the kinds of events the device reports.
1646 DHLOGI("Ctor Device for get event mask, fd: %{public}d, path: %{public}s", fd, path.c_str());
1647 ioctl(fd, EVIOCGBIT(0, sizeof(evBitmask)), evBitmask);
1648 ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keyBitmask)), keyBitmask);
1649 ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absBitmask)), absBitmask);
1650 ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relBitmask)), relBitmask);
1651 }
1652
~Device()1653 InputHub::Device::~Device()
1654 {
1655 Close();
1656 }
1657
Close()1658 void InputHub::Device::Close()
1659 {
1660 if (fd >= 0) {
1661 ::close(fd);
1662 fd = UN_INIT_FD_VALUE;
1663 }
1664 }
1665
Enable()1666 int32_t InputHub::Device::Enable()
1667 {
1668 char canonicalPath[PATH_MAX + 1] = {0x00};
1669
1670 if (path.length() == 0 || path.length() > PATH_MAX || realpath(path.c_str(), canonicalPath) == nullptr) {
1671 DHLOGE("path check fail, error path: %{public}s", path.c_str());
1672 return ERR_DH_INPUT_HUB_DEVICE_ENABLE_FAIL;
1673 }
1674 fd = open(canonicalPath, O_RDWR | O_CLOEXEC | O_NONBLOCK);
1675 if (fd < 0) {
1676 DHLOGE("could not open %{public}s, %{public}s\n", path.c_str(), ConvertErrNo().c_str());
1677 return ERR_DH_INPUT_HUB_DEVICE_ENABLE_FAIL;
1678 }
1679 enabled = true;
1680 return DH_SUCCESS;
1681 }
1682
Disable()1683 int32_t InputHub::Device::Disable()
1684 {
1685 Close();
1686 enabled = false;
1687 return DH_SUCCESS;
1688 }
1689
HasValidFd() const1690 bool InputHub::Device::HasValidFd() const
1691 {
1692 return !isVirtual && enabled;
1693 }
1694 } // namespace DistributedInput
1695 } // namespace DistributedHardware
1696 } // namespace OHOS
1697