1 /*
2 * Copyright (c) 2021-2025 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 return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
564 }
565 GenerateDescriptor(device->identifier);
566 IncreaseLogTimes(device->identifier.descriptor);
567 RecordDeviceLog(devicePath, device->identifier);
568 std::string descriptor = device->identifier.descriptor;
569 if (MakeDevice(fd, std::move(device)) < 0) {
570 if (IsNeedPrintLog(descriptor)) {
571 DHLOGI("Opening device error: %{public}s", devicePath.c_str());
572 }
573 return ERR_DH_INPUT_HUB_MAKE_DEVICE_FAIL;
574 }
575
576 DHLOGI("Opening device finish: %{public}s", devicePath.c_str());
577 return DH_SUCCESS;
578 }
579
RecordSkipDevicePath(std::string path)580 void InputHub::RecordSkipDevicePath(std::string path)
581 {
582 std::lock_guard<std::mutex> lock(skipDevicePathsMutex_);
583 skipDevicePaths_.insert(path);
584 }
585
IsSkipDevicePath(const std::string & path)586 bool InputHub::IsSkipDevicePath(const std::string &path)
587 {
588 std::lock_guard<std::mutex> lock(skipDevicePathsMutex_);
589 return skipDevicePaths_.find(path) != skipDevicePaths_.end();
590 }
591
IncreaseLogTimes(const std::string & dhId)592 void InputHub::IncreaseLogTimes(const std::string& dhId)
593 {
594 if (logTimesMap_.find(dhId) != logTimesMap_.end() && logTimesMap_[dhId] >= INT32_MAX - 1) {
595 logTimesMap_[dhId] = 0;
596 } else {
597 logTimesMap_[dhId]++;
598 }
599 }
600
IsNeedPrintLog(const std::string & dhId) const601 bool InputHub::IsNeedPrintLog(const std::string& dhId) const
602 {
603 return logTimesMap_.find(dhId) == logTimesMap_.end() || logTimesMap_.at(dhId) <= MAX_LOG_TIMES;
604 }
605
QueryInputDeviceInfo(int fd,std::unique_ptr<Device> & device)606 int32_t InputHub::QueryInputDeviceInfo(int fd, std::unique_ptr<Device> &device)
607 {
608 char buffer[INPUT_EVENT_BUFFER_SIZE] = {0};
609 // Get device name.
610 if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
611 DHLOGE("Could not get device name for %{public}s", ConvertErrNo().c_str());
612 } else {
613 buffer[sizeof(buffer) - 1] = '\0';
614 device->identifier.name = buffer;
615 }
616 DHLOGD("QueryInputDeviceInfo deviceName: %{public}s", buffer);
617 // If the device is already a virtual device, don't monitor it.
618 if (device->identifier.name.find(VIRTUAL_DEVICE_NAME) != std::string::npos) {
619 DHLOGE("this is a virtual driver, skip it.");
620 RecordSkipDevicePath(device->path);
621 return ERR_DH_INPUT_HUB_IS_VIRTUAL_DEVICE;
622 }
623 // Get device driver version.
624 int driverVersion;
625 if (ioctl(fd, EVIOCGVERSION, &driverVersion)) {
626 DHLOGE("could not get driver version for %{public}s\n", ConvertErrNo().c_str());
627 RecordSkipDevicePath(device->path);
628 return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
629 }
630 // Get device identifier.
631 struct input_id inputId;
632 if (ioctl(fd, EVIOCGID, &inputId)) {
633 DHLOGE("could not get device input id for %{public}s\n", ConvertErrNo().c_str());
634 RecordSkipDevicePath(device->path);
635 return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
636 }
637 device->identifier.bus = inputId.bustype;
638 device->identifier.product = inputId.product;
639 device->identifier.vendor = inputId.vendor;
640 device->identifier.version = inputId.version;
641 // Get device physical physicalPath.
642 if (ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
643 DHLOGE("could not get physicalPath for %{public}s\n", ConvertErrNo().c_str());
644 } else {
645 buffer[sizeof(buffer) - 1] = '\0';
646 device->identifier.physicalPath = buffer;
647 }
648 // Get device unique id.
649 if (ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
650 DHLOGE("could not get idstring for %{public}s\n", ConvertErrNo().c_str());
651 } else {
652 buffer[sizeof(buffer) - 1] = '\0';
653 device->identifier.uniqueId = buffer;
654 }
655
656 QueryEventInfo(fd, device);
657 return DH_SUCCESS;
658 }
659
QueryEventInfo(int fd,std::unique_ptr<Device> & device)660 void InputHub::QueryEventInfo(int fd, std::unique_ptr<Device> &device)
661 {
662 if (device == nullptr) {
663 DHLOGE("device is nullptr!");
664 return;
665 }
666 if (IsNeedPrintLog(device->identifier.descriptor)) {
667 DHLOGI("QueryEventInfo: devName: %{public}s, dhId: %{public}s!", device->identifier.name.c_str(),
668 GetAnonyString(device->identifier.descriptor).c_str());
669 }
670 struct libevdev *dev = GetLibEvDev(fd);
671 if (dev == nullptr) {
672 if (IsNeedPrintLog(device->identifier.descriptor)) {
673 DHLOGE("dev is nullptr");
674 }
675 return;
676 }
677 GetEventTypes(dev, device->identifier);
678 GetEventKeys(dev, device->identifier);
679 GetABSInfo(dev, device->identifier);
680 GetRELTypes(dev, device->identifier);
681 GetProperties(dev, device->identifier);
682
683 GetMSCBits(fd, device);
684 GetLEDBits(fd, device);
685 GetSwitchBits(fd, device);
686 GetRepeatBits(fd, device);
687
688 libevdev_free(dev);
689 }
690
GetEventMask(int fd,const std::string & eventName,uint32_t type,std::size_t arrayLength,uint8_t * whichBitMask) const691 void InputHub::GetEventMask(int fd, const std::string &eventName, uint32_t type,
692 std::size_t arrayLength, uint8_t *whichBitMask) const
693 {
694 int32_t rc = ioctl(fd, EVIOCGBIT(type, arrayLength), whichBitMask);
695 if (rc < 0) {
696 DHLOGE("Could not get events %{public}s mask: %{public}s", eventName.c_str(), strerror(errno));
697 }
698 }
699
GetMSCBits(int fd,std::unique_ptr<Device> & device)700 void InputHub::GetMSCBits(int fd, std::unique_ptr<Device> &device)
701 {
702 uint8_t mscBitmask[NBYTES(MSC_MAX)] {};
703 GetEventMask(fd, "msc", EV_MSC, sizeof(mscBitmask), mscBitmask);
704
705 for (uint32_t msc = MSC_SERIAL; msc < MSC_MAX; ++msc) {
706 if (TestBit(EV_MSC, device->evBitmask) && TestBit(msc, mscBitmask)) {
707 DHLOGI("Get MSC event: %{public}d", msc);
708 device->identifier.miscellaneous.push_back(msc);
709 }
710 }
711 }
712
GetLEDBits(int fd,std::unique_ptr<Device> & device)713 void InputHub::GetLEDBits(int fd, std::unique_ptr<Device> &device)
714 {
715 uint8_t ledBitmask[NBYTES(LED_MAX)] {};
716 GetEventMask(fd, "led", EV_LED, sizeof(ledBitmask), ledBitmask);
717 for (uint32_t led = LED_NUML; led < LED_MAX; ++led) {
718 if (TestBit(EV_LED, device->evBitmask) && TestBit(led, ledBitmask)) {
719 DHLOGI("Get LED event: %{public}d", led);
720 device->identifier.leds.push_back(led);
721 }
722 }
723 }
724
GetSwitchBits(int fd,std::unique_ptr<Device> & device)725 void InputHub::GetSwitchBits(int fd, std::unique_ptr<Device> &device)
726 {
727 uint8_t switchBitmask[NBYTES(SW_MAX)] {};
728 GetEventMask(fd, "switch", EV_SW, sizeof(switchBitmask), switchBitmask);
729
730 for (uint32_t sw = SW_LID; sw < SW_MAX; ++sw) {
731 if (TestBit(EV_SW, device->evBitmask) && TestBit(sw, switchBitmask)) {
732 DHLOGI("Get Switch event: %{public}d", sw);
733 device->identifier.switchs.push_back(sw);
734 }
735 }
736 }
737
GetRepeatBits(int fd,std::unique_ptr<Device> & device)738 void InputHub::GetRepeatBits(int fd, std::unique_ptr<Device> &device)
739 {
740 uint8_t repBitmask[NBYTES(REP_MAX)] {};
741 GetEventMask(fd, "repeat", EV_REP, sizeof(repBitmask), repBitmask);
742
743 for (uint32_t rep = REP_DELAY; rep < REP_MAX; ++rep) {
744 if (TestBit(EV_REP, device->evBitmask) && TestBit(rep, repBitmask)) {
745 DHLOGI("Get Repeat event: %{public}d", rep);
746 device->identifier.repeats.push_back(rep);
747 }
748 }
749 }
750
GetLibEvDev(int fd)751 struct libevdev* InputHub::GetLibEvDev(int fd)
752 {
753 struct libevdev *dev = nullptr;
754 int rc = 1;
755 rc = libevdev_new_from_fd(fd, &dev);
756 if (rc < 0) {
757 DHLOGE("Failed to init libevdev (%{public}s)", strerror(-rc));
758 return nullptr;
759 }
760 return dev;
761 }
762
GetEventTypes(struct libevdev * dev,InputDevice & identifier)763 void InputHub::GetEventTypes(struct libevdev *dev, InputDevice &identifier)
764 {
765 for (uint32_t eventType = 0; eventType < EV_CNT; eventType++) {
766 if (!libevdev_has_event_type(dev, eventType)) {
767 DHLOGD("The device is not support eventType: %{public}d", eventType);
768 continue;
769 }
770 identifier.eventTypes.push_back(eventType);
771 }
772 }
773
GetEventKeys(struct libevdev * dev,InputDevice & identifier)774 int32_t InputHub::GetEventKeys(struct libevdev *dev, InputDevice &identifier)
775 {
776 if (!libevdev_has_event_type(dev, EV_KEY)) {
777 if (IsNeedPrintLog(identifier.descriptor)) {
778 DHLOGE("The device doesn't has EV_KEY type!");
779 }
780 return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
781 }
782 for (uint32_t eventKey = 0; eventKey < KEY_CNT; eventKey++) {
783 if (!libevdev_has_event_code(dev, EV_KEY, eventKey)) {
784 DHLOGD("The device is not support eventKey: %{public}d", eventKey);
785 continue;
786 }
787 identifier.eventKeys.push_back(eventKey);
788 }
789 return DH_SUCCESS;
790 }
791
GetABSInfo(struct libevdev * dev,InputDevice & identifier)792 int32_t InputHub::GetABSInfo(struct libevdev *dev, InputDevice &identifier)
793 {
794 if (!libevdev_has_event_type(dev, EV_ABS)) {
795 if (IsNeedPrintLog(identifier.descriptor)) {
796 DHLOGE("The device doesn't has EV_ABS type!");
797 }
798 return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
799 }
800 DHLOGI("The device has abs info, devName: %{public}s, dhId: %{public}s!",
801 identifier.name.c_str(), GetAnonyString(identifier.descriptor).c_str());
802 for (uint32_t absType = 0; absType < ABS_CNT; absType++) {
803 if (!libevdev_has_event_code(dev, EV_ABS, absType)) {
804 DHLOGD("The device is not support absType: %{public}d", absType);
805 continue;
806 }
807 identifier.absTypes.push_back(absType);
808 const struct input_absinfo *abs = libevdev_get_abs_info(dev, absType);
809 if (abs == nullptr) {
810 DHLOGE("absInfo is nullptr!");
811 continue;
812 }
813 identifier.absInfos[absType].push_back(abs->value);
814 identifier.absInfos[absType].push_back(abs->minimum);
815 identifier.absInfos[absType].push_back(abs->maximum);
816 identifier.absInfos[absType].push_back(abs->fuzz);
817 identifier.absInfos[absType].push_back(abs->flat);
818 identifier.absInfos[absType].push_back(abs->resolution);
819 }
820 return DH_SUCCESS;
821 }
822
GetRELTypes(struct libevdev * dev,InputDevice & identifier)823 int32_t InputHub::GetRELTypes(struct libevdev *dev, InputDevice &identifier)
824 {
825 if (!libevdev_has_event_type(dev, EV_REL)) {
826 if (IsNeedPrintLog(identifier.descriptor)) {
827 DHLOGE("The device doesn't has EV_REL type!");
828 }
829 return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
830 }
831 for (uint32_t code = 0; code < REL_CNT; code++) {
832 if (!libevdev_has_event_code(dev, EV_REL, code)) {
833 DHLOGD("The device is not support rel code: %{public}d", code);
834 continue;
835 }
836 identifier.relTypes.push_back(code);
837 }
838 return DH_SUCCESS;
839 }
840
GetProperties(struct libevdev * dev,InputDevice & identifier)841 void InputHub::GetProperties(struct libevdev *dev, InputDevice &identifier)
842 {
843 for (uint32_t prop = 0; prop < INPUT_PROP_CNT; prop++) {
844 if (libevdev_has_property(dev, prop)) {
845 DHLOGI("QueryInputDeviceInfo rel prop: %{public}d", prop);
846 identifier.properties.push_back(prop);
847 }
848 }
849 }
850
MakeDevice(int fd,std::unique_ptr<Device> device)851 int32_t InputHub::MakeDevice(int fd, std::unique_ptr<Device> device)
852 {
853 // See if this is a multi-touch touchscreen device.
854 if (TestBit(BTN_TOUCH, device->keyBitmask) &&
855 TestBit(ABS_MT_POSITION_X, device->absBitmask) &&
856 TestBit(ABS_MT_POSITION_Y, device->absBitmask)) {
857 QueryLocalTouchScreenInfo(fd, device);
858 device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
859 } else if (TestBit(BTN_TOUCH, device->keyBitmask) &&
860 TestBit(ABS_X, device->absBitmask) &&
861 TestBit(ABS_Y, device->absBitmask)) {
862 QueryLocalTouchScreenInfo(fd, device);
863 device->classes |= INPUT_DEVICE_CLASS_TOUCH;
864 }
865
866 // See if this is a cursor device such as a trackball or mouse.
867 if (TestBit(BTN_MOUSE, device->keyBitmask)
868 && TestBit(REL_X, device->relBitmask)
869 && TestBit(REL_Y, device->relBitmask)) {
870 device->classes |= INPUT_DEVICE_CLASS_CURSOR;
871 }
872
873 // for Linux version 4.14.116, touchpad recognized as mouse and keyboard at same time,
874 // need to avoid device->classes to be 0x09, which mmi can't handler.
875 // See if this is a keyboard.
876 if (device->classes == 0) {
877 bool haveKeyboardKeys = ContainsNonZeroByte(device->keyBitmask, 0, SizeofBitArray(BTN_MISC));
878 if (haveKeyboardKeys) {
879 device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
880 }
881 }
882
883 // If the device isn't recognized as something we handle, don't monitor it.
884 if (device->classes == 0) {
885 if (IsNeedPrintLog(device->identifier.descriptor)) {
886 DHLOGI("Dropping device: name='%{public}s'", device->identifier.name.c_str());
887 }
888 return ERR_DH_INPUT_HUB_MAKE_DEVICE_FAIL;
889 }
890
891 if (RegisterDeviceForEpollLocked(*device) != DH_SUCCESS) {
892 return ERR_DH_INPUT_HUB_MAKE_DEVICE_FAIL;
893 }
894
895 device->identifier.classes = device->classes;
896
897 DHLOGI("inputType=%{public}d", inputTypes_.load());
898 DHLOGI("New device: fd=%{public}d, name='%{public}s', classes=0x%{public}x", fd, device->identifier.name.c_str(),
899 device->classes);
900
901 AddDeviceLocked(std::move(device));
902 return DH_SUCCESS;
903 }
904
QueryLocalTouchScreenInfo(int fd,std::unique_ptr<Device> & device)905 int32_t InputHub::QueryLocalTouchScreenInfo(int fd, std::unique_ptr<Device> &device)
906 {
907 LocalTouchScreenInfo info = DInputContext::GetInstance().GetLocalTouchScreenInfo();
908 device->identifier.classes |= INPUT_DEVICE_CLASS_TOUCH_MT;
909 info.localAbsInfo.deviceInfo = device->identifier;
910
911 struct input_absinfo absInfo;
912 ioctl(fd, EVIOCGABS(ABS_MT_POSITION_X), &absInfo);
913 info.localAbsInfo.absXMin = absInfo.minimum;
914 info.localAbsInfo.absXMax = absInfo.maximum;
915 info.localAbsInfo.absMtPositionXMin = absInfo.minimum;
916 info.localAbsInfo.absMtPositionXMax = absInfo.maximum;
917 info.sinkPhyWidth = static_cast<uint32_t>(absInfo.maximum + 1);
918
919 ioctl(fd, EVIOCGABS(ABS_MT_POSITION_Y), &absInfo);
920 info.localAbsInfo.absYMin = absInfo.minimum;
921 info.localAbsInfo.absYMax = absInfo.maximum;
922 info.localAbsInfo.absMtPositionYMin = absInfo.minimum;
923 info.localAbsInfo.absMtPositionYMax = absInfo.maximum;
924 info.sinkPhyHeight = static_cast<uint32_t>(absInfo.maximum + 1);
925
926 ioctl(fd, EVIOCGABS(ABS_PRESSURE), &absInfo);
927 info.localAbsInfo.absPressureMin = absInfo.minimum;
928 info.localAbsInfo.absPressureMax = absInfo.maximum;
929 info.localAbsInfo.absMtPressureMin = absInfo.minimum;
930 info.localAbsInfo.absMtPressureMax = absInfo.maximum;
931
932 ioctl(fd, EVIOCGABS(ABS_MT_TOUCH_MAJOR), &absInfo);
933 info.localAbsInfo.absMtTouchMajorMin = absInfo.minimum;
934 info.localAbsInfo.absMtTouchMajorMax = absInfo.maximum;
935
936 ioctl(fd, EVIOCGABS(ABS_MT_TOUCH_MINOR), &absInfo);
937 info.localAbsInfo.absMtTouchMinorMin = absInfo.minimum;
938 info.localAbsInfo.absMtTouchMinorMax = absInfo.maximum;
939
940 ioctl(fd, EVIOCGABS(ABS_MT_ORIENTATION), &absInfo);
941 info.localAbsInfo.absMtOrientationMin = absInfo.minimum;
942 info.localAbsInfo.absMtOrientationMax = absInfo.maximum;
943
944 ioctl(fd, EVIOCGABS(ABS_MT_BLOB_ID), &absInfo);
945 info.localAbsInfo.absMtBlobIdMin = absInfo.minimum;
946 info.localAbsInfo.absMtBlobIdMax = absInfo.maximum;
947
948 ioctl(fd, EVIOCGABS(ABS_MT_TRACKING_ID), &absInfo);
949 info.localAbsInfo.absMtTrackingIdMin = absInfo.minimum;
950 info.localAbsInfo.absMtTrackingIdMax = absInfo.maximum;
951
952 DInputContext::GetInstance().SetLocalTouchScreenInfo(info);
953 return DH_SUCCESS;
954 }
955
StringPrintf(const char * format,...) const956 std::string InputHub::StringPrintf(const char *format, ...) const
957 {
958 char space[SPACELENGTH] = {0};
959 va_list ap;
960 va_start(ap, format);
961 std::string result;
962 int32_t ret = vsnprintf_s(space, sizeof(space), sizeof(space) - 1, format, ap);
963 if (ret >= DH_SUCCESS && static_cast<size_t>(ret) < sizeof(space)) {
964 result = space;
965 } else {
966 va_end(ap);
967 return "the buffer is overflow!";
968 }
969 va_end(ap);
970 return result;
971 }
972
GenerateDescriptor(InputDevice & identifier) const973 void InputHub::GenerateDescriptor(InputDevice &identifier) const
974 {
975 std::string rawDescriptor;
976 rawDescriptor += StringPrintf(":%04x:%04x:", identifier.vendor,
977 identifier.product);
978 // add handling for USB devices to not uniqueify kbs that show up twice
979 if (!identifier.uniqueId.empty()) {
980 rawDescriptor += "uniqueId:";
981 rawDescriptor += identifier.uniqueId;
982 }
983 if (!identifier.physicalPath.empty()) {
984 rawDescriptor += "physicalPath:";
985 rawDescriptor += identifier.physicalPath;
986 }
987 if (!identifier.name.empty()) {
988 rawDescriptor += "name:";
989 std::string name = identifier.name;
990 rawDescriptor += regex_replace(name, std::regex(" "), "");
991 }
992
993 identifier.descriptor = DH_ID_PREFIX + Sha256(rawDescriptor);
994 if (IsNeedPrintLog(identifier.descriptor)) {
995 DHLOGI("Created descriptor: raw=%{public}s, cooked=%{public}s", rawDescriptor.c_str(),
996 GetAnonyString(identifier.descriptor).c_str());
997 }
998 }
999
RegisterDeviceForEpollLocked(const Device & device)1000 int32_t InputHub::RegisterDeviceForEpollLocked(const Device &device)
1001 {
1002 int32_t result = RegisterFdForEpoll(device.fd);
1003 if (result != DH_SUCCESS) {
1004 DHLOGE("Could not add input device fd to epoll for device, path: %{public}s", device.path.c_str());
1005 return result;
1006 }
1007 return result;
1008 }
1009
RegisterFdForEpoll(int fd)1010 int32_t InputHub::RegisterFdForEpoll(int fd)
1011 {
1012 struct epoll_event eventItem = {};
1013 eventItem.events = EPOLLIN | EPOLLWAKEUP;
1014 eventItem.data.fd = fd;
1015 if (epoll_ctl(epollFd_, EPOLL_CTL_ADD, fd, &eventItem)) {
1016 DHLOGE("Could not add fd to epoll instance: %{public}s", ConvertErrNo().c_str());
1017 return -errno;
1018 }
1019 return DH_SUCCESS;
1020 }
1021
AddDeviceLocked(std::unique_ptr<Device> device)1022 void InputHub::AddDeviceLocked(std::unique_ptr<Device> device)
1023 {
1024 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1025 openingDevices_.push_back(std::move(device));
1026 }
1027
CloseDeviceLocked(Device & device)1028 void InputHub::CloseDeviceLocked(Device &device)
1029 {
1030 DHLOGI("Removed device: path=%{public}s name=%{public}s fd=%{public}d classes=0x%{public}x",
1031 device.path.c_str(), device.identifier.name.c_str(), device.fd, device.classes);
1032
1033 UnregisterDeviceFromEpollLocked(device);
1034 device.Close();
1035 {
1036 std::lock_guard<std::mutex> devicesLock(devicesMutex_);
1037 closingDevices_.push_back(std::move(devices_[device.path]));
1038 devices_.erase(device.path);
1039 }
1040 }
1041
CloseDeviceForAllLocked(Device & device)1042 void InputHub::CloseDeviceForAllLocked(Device &device)
1043 {
1044 DHLOGI("Removed device: path=%{public}s name=%{public}s fd=%{public}d classes=0x%{public}x",
1045 device.path.c_str(), device.identifier.name.c_str(), device.fd, device.classes);
1046
1047 UnregisterDeviceFromEpollLocked(device);
1048 device.Close();
1049 closingDevices_.push_back(std::move(devices_[device.path]));
1050 devices_.erase(device.path);
1051 }
1052
UnregisterDeviceFromEpollLocked(const Device & device) const1053 int32_t InputHub::UnregisterDeviceFromEpollLocked(const Device &device) const
1054 {
1055 if (device.HasValidFd()) {
1056 int32_t result = UnregisterFdFromEpoll(device.fd);
1057 if (result != DH_SUCCESS) {
1058 DHLOGE("Could not remove input device fd from epoll for device, path: %{public}s", device.path.c_str());
1059 return result;
1060 }
1061 }
1062 return DH_SUCCESS;
1063 }
1064
UnregisterFdFromEpoll(int fd) const1065 int32_t InputHub::UnregisterFdFromEpoll(int fd) const
1066 {
1067 if (epoll_ctl(epollFd_, EPOLL_CTL_DEL, fd, nullptr)) {
1068 DHLOGE("Could not remove fd from epoll instance: %{public}s", ConvertErrNo().c_str());
1069 return ERR_DH_INPUT_HUB_UNREGISTER_FD_FAIL;
1070 }
1071 return DH_SUCCESS;
1072 }
1073
ReadNotifyLocked()1074 int32_t InputHub::ReadNotifyLocked()
1075 {
1076 size_t res;
1077 char eventBuf[EVENT_BUFFER_MAX] = {0};
1078 struct inotify_event *event;
1079
1080 DHLOGI("readNotify nfd: %{public}d\n", iNotifyFd_);
1081 res = static_cast<size_t>(read(iNotifyFd_, eventBuf, sizeof(eventBuf)));
1082 if (res < sizeof(*event)) {
1083 if (errno == EINTR) {
1084 return DH_SUCCESS;
1085 }
1086 DHLOGE("could not get event, %{public}s\n", ConvertErrNo().c_str());
1087 return ERR_DH_INPUT_HUB_GET_EVENT_FAIL;
1088 }
1089
1090 {
1091 size_t eventSize = 0;
1092 size_t eventPos = 0;
1093 while (res >= sizeof(*event) && eventPos < static_cast<size_t>(EVENT_BUFFER_MAX)) {
1094 event = reinterpret_cast<struct inotify_event *>(eventBuf + eventPos);
1095 JudgeDeviceOpenOrClose(*event);
1096 eventSize = sizeof(*event) + event->len;
1097 res -= eventSize;
1098 eventPos += eventSize;
1099 }
1100 }
1101 return DH_SUCCESS;
1102 }
1103
JudgeDeviceOpenOrClose(const inotify_event & event)1104 void InputHub::JudgeDeviceOpenOrClose(const inotify_event &event)
1105 {
1106 if (event.len) {
1107 if (event.wd == inputWd_) {
1108 std::string filename = std::string(DEVICE_PATH) + "/" + event.name;
1109 if (event.mask & IN_CREATE) {
1110 OpenInputDeviceLocked(filename);
1111 } else {
1112 DHLOGI("Removing device '%{public}s' due to inotify event\n", filename.c_str());
1113 CloseDeviceByPathLocked(filename);
1114 }
1115 } else {
1116 DHLOGI("Unexpected inotify event, wd = %i", event.wd);
1117 }
1118 }
1119 }
1120
CloseDeviceByPathLocked(const std::string & devicePath)1121 void InputHub::CloseDeviceByPathLocked(const std::string &devicePath)
1122 {
1123 Device* device = GetDeviceByPathLocked(devicePath);
1124 if (device) {
1125 CloseDeviceLocked(*device);
1126 return;
1127 }
1128 DHLOGI("Remove device: %{public}s not found, device may already have been removed.", devicePath.c_str());
1129 }
1130
CloseAllDevicesLocked()1131 void InputHub::CloseAllDevicesLocked()
1132 {
1133 DHLOGI("Close All Devices");
1134 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1135 while (!devices_.empty()) {
1136 CloseDeviceForAllLocked(*(devices_.begin()->second));
1137 }
1138 }
1139
GetDeviceByPathLocked(const std::string & devicePath)1140 InputHub::Device* InputHub::GetDeviceByPathLocked(const std::string &devicePath)
1141 {
1142 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1143 for (const auto &[id, device] : devices_) {
1144 if (device->path == devicePath) {
1145 return device.get();
1146 }
1147 }
1148 return nullptr;
1149 }
1150
GetDeviceByFdLocked(int fd)1151 InputHub::Device* InputHub::GetDeviceByFdLocked(int fd)
1152 {
1153 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1154 for (const auto &[id, device] : devices_) {
1155 if (device->fd == fd) {
1156 return device.get();
1157 }
1158 }
1159 return nullptr;
1160 }
1161
GetSupportDeviceByFd(int fd)1162 InputHub::Device* InputHub::GetSupportDeviceByFd(int fd)
1163 {
1164 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1165 for (const auto &[id, device] : devices_) {
1166 if (device != nullptr && device->fd == fd) {
1167 return device.get();
1168 }
1169 }
1170 return nullptr;
1171 }
1172
ContainsNonZeroByte(const uint8_t * array,uint32_t startIndex,uint32_t endIndex)1173 bool InputHub::ContainsNonZeroByte(const uint8_t *array, uint32_t startIndex, uint32_t endIndex)
1174 {
1175 const uint8_t* end = array + endIndex;
1176 array += startIndex;
1177 while (array != end) {
1178 if (*(array++) != 0) {
1179 return true;
1180 }
1181 }
1182 return false;
1183 }
1184
ProcessEventTimestamp(const input_event & event)1185 int64_t InputHub::ProcessEventTimestamp(const input_event &event)
1186 {
1187 const int64_t inputEventTime = event.input_event_sec * 1000000000LL + event.input_event_usec * 1000LL;
1188 return inputEventTime;
1189 }
1190
TestBit(uint32_t bit,const uint8_t * array)1191 bool InputHub::TestBit(uint32_t bit, const uint8_t *array)
1192 {
1193 constexpr int units = 8;
1194 return (array)[(bit) / units] & (1 << ((bit) % units));
1195 }
1196
SizeofBitArray(uint32_t bit)1197 uint32_t InputHub::SizeofBitArray(uint32_t bit)
1198 {
1199 constexpr int round = 7;
1200 constexpr int divisor = 8;
1201 return ((bit) + round) / divisor;
1202 }
1203
SaveAffectDhId(bool isEnable,const std::string & dhId,AffectDhIds & affDhIds)1204 void InputHub::SaveAffectDhId(bool isEnable, const std::string &dhId, AffectDhIds &affDhIds)
1205 {
1206 if (isEnable) {
1207 affDhIds.sharingDhIds.push_back(dhId);
1208 } else {
1209 affDhIds.noSharingDhIds.push_back(dhId);
1210 }
1211 }
1212
SetSupportInputType(bool enabled,const uint32_t & inputTypes)1213 AffectDhIds InputHub::SetSupportInputType(bool enabled, const uint32_t &inputTypes)
1214 {
1215 AffectDhIds affDhIds;
1216 inputTypes_ = inputTypes;
1217 DHLOGI("SetSupportInputType: inputTypes=0x%x,", inputTypes_.load());
1218 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1219 for (const auto &[id, device] : devices_) {
1220 if (device->classes & inputTypes_) {
1221 device->isShare = enabled;
1222 DHLOGW("ByType dhid:%{public}s, isshare:%{public}d",
1223 GetAnonyString(device->identifier.descriptor).c_str(), enabled);
1224 SaveAffectDhId(enabled, device->identifier.descriptor, affDhIds);
1225 }
1226 }
1227
1228 return affDhIds;
1229 }
1230
SetSharingDevices(bool enabled,std::vector<std::string> dhIds)1231 AffectDhIds InputHub::SetSharingDevices(bool enabled, std::vector<std::string> dhIds)
1232 {
1233 AffectDhIds affDhIds;
1234 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1235 DHLOGI("SetSharingDevices start");
1236 for (auto dhId : dhIds) {
1237 DHLOGI("SetSharingDevices dhId: %{public}s, size: %{public}zu, enabled: %{public}d",
1238 GetAnonyString(dhId).c_str(), devices_.size(), enabled);
1239 sharedDHIds_[dhId] = enabled;
1240 for (const auto &[id, device] : devices_) {
1241 DHLOGI("deviceName %{public}s ,dhId: %{public}s ", device->identifier.name.c_str(),
1242 GetAnonyString(device->identifier.descriptor).c_str());
1243 if (device->identifier.descriptor == dhId) {
1244 device->isShare = enabled;
1245 DHLOGW("dhid:%{public}s, isshare:%{public}d",
1246 GetAnonyString(device->identifier.descriptor).c_str(), enabled);
1247 SaveAffectDhId(enabled, device->identifier.descriptor, affDhIds);
1248 break;
1249 }
1250 }
1251 }
1252 DHLOGI("SetSharingDevices end");
1253 return affDhIds;
1254 }
1255
GetSharingDevices()1256 std::vector<std::string> InputHub::GetSharingDevices()
1257 {
1258 std::vector<std::string> sharingDevices;
1259 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1260 for (const auto &[id, device] : devices_) {
1261 if (device->isShare) {
1262 DHLOGI("Find sharing dhid: %{public}s", GetAnonyString(device->identifier.descriptor).c_str());
1263 sharingDevices.push_back(device->identifier.descriptor);
1264 }
1265 }
1266 return sharingDevices;
1267 }
1268
GetSharedMousePathByDhId(const std::vector<std::string> & dhIds,std::string & sharedMousePath,std::string & sharedMouseDhId)1269 void InputHub::GetSharedMousePathByDhId(const std::vector<std::string> &dhIds, std::string &sharedMousePath,
1270 std::string &sharedMouseDhId)
1271 {
1272 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1273 DHLOGI("GetSharedMousePathByDhId: devices_.size:%{public}zu,", devices_.size());
1274 for (const auto &dhId : dhIds) {
1275 for (const auto &[id, device] : devices_) {
1276 if (device == nullptr) {
1277 DHLOGE("device is nullptr");
1278 continue;
1279 }
1280 DHLOGI("descriptor:%{public}s, isShare[%{public}d], type[%{public}d]",
1281 GetAnonyString(device->identifier.descriptor).c_str(), device->isShare, device->classes);
1282 if ((device->identifier.descriptor == dhId) && ((device->classes & INPUT_DEVICE_CLASS_CURSOR) != 0 ||
1283 (device->classes & INPUT_DEVICE_CLASS_TOUCH) != 0 ||
1284 ((device->classes & INPUT_DEVICE_CLASS_TOUCH_MT) != 0 && IsTouchPad(device->identifier)))) {
1285 sharedMouseDhId = dhId;
1286 sharedMousePath = device->path;
1287 return; // return First shared mouse
1288 }
1289 }
1290 }
1291 }
1292
GetSharedKeyboardPathsByDhIds(const std::vector<std::string> & dhIds,std::vector<std::string> & sharedKeyboardPaths,std::vector<std::string> & sharedKeyboardDhIds)1293 void InputHub::GetSharedKeyboardPathsByDhIds(const std::vector<std::string> &dhIds,
1294 std::vector<std::string> &sharedKeyboardPaths, std::vector<std::string> &sharedKeyboardDhIds)
1295 {
1296 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1297 DHLOGI("GetSharedKeyboardPathsByDhIds: devices_.size:%{public}zu,", devices_.size());
1298 for (const auto &dhId : dhIds) {
1299 for (const auto &[id, device] : devices_) {
1300 if (device == nullptr) {
1301 DHLOGE("device is nullptr");
1302 continue;
1303 }
1304 DHLOGI("descriptor:%{public}s, isShare[%{public}d], type[%{public}d]",
1305 GetAnonyString(device->identifier.descriptor).c_str(), device->isShare, device->classes);
1306 if ((device->identifier.descriptor == dhId) &&
1307 ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0)) {
1308 sharedKeyboardDhIds.push_back(dhId);
1309 sharedKeyboardPaths.push_back(device->path);
1310 }
1311 }
1312 }
1313 }
1314
GetDevicesInfoByType(const uint32_t inputTypes,std::map<int32_t,std::string> & datas)1315 void InputHub::GetDevicesInfoByType(const uint32_t inputTypes, std::map<int32_t, std::string> &datas)
1316 {
1317 uint32_t dhType = 0;
1318
1319 if ((inputTypes & static_cast<uint32_t>(DInputDeviceType::MOUSE)) != 0) {
1320 dhType |= INPUT_DEVICE_CLASS_CURSOR;
1321 }
1322
1323 if ((inputTypes & static_cast<uint32_t>(DInputDeviceType::KEYBOARD)) != 0) {
1324 dhType |= INPUT_DEVICE_CLASS_KEYBOARD;
1325 }
1326
1327 if ((inputTypes & static_cast<uint32_t>(DInputDeviceType::TOUCHSCREEN)) != 0) {
1328 dhType |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
1329 }
1330
1331 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1332 for (const auto &[id, device] : devices_) {
1333 if (device->classes & dhType) {
1334 datas.insert(std::pair<int32_t, std::string>(device->fd, device->identifier.descriptor));
1335 }
1336 }
1337 }
1338
GetDevicesInfoByDhId(std::vector<std::string> dhidsVec,std::map<int32_t,std::string> & datas)1339 void InputHub::GetDevicesInfoByDhId(std::vector<std::string> dhidsVec, std::map<int32_t, std::string> &datas)
1340 {
1341 for (auto dhId : dhidsVec) {
1342 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1343 for (const auto &[id, device] : devices_) {
1344 if (device->identifier.descriptor == dhId) {
1345 datas.insert(std::pair<int32_t, std::string>(device->fd, dhId));
1346 }
1347 }
1348 }
1349 }
1350
IsAllDevicesStoped()1351 bool InputHub::IsAllDevicesStoped()
1352 {
1353 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1354 for (const auto &[dhId, isShared] : sharedDHIds_) {
1355 DHLOGI("the dhId: %{public}s, isShared: %{public}d", GetAnonyString(dhId).c_str(), isShared);
1356 if (isShared) {
1357 return false;
1358 }
1359 }
1360 return true;
1361 }
1362
RecordDeviceLog(const std::string & devicePath,const InputDevice & identifier)1363 void InputHub::RecordDeviceLog(const std::string &devicePath, const InputDevice &identifier)
1364 {
1365 if (IsNeedPrintLog(identifier.descriptor)) {
1366 DHLOGI("add device: %{public}s\n", devicePath.c_str());
1367 DHLOGI(" bus: %{public}04x\n"
1368 " vendor %{public}04x\n"
1369 " product %{public}04x\n"
1370 " version %{public}04x\n",
1371 identifier.bus, identifier.vendor, identifier.product, identifier.version);
1372 DHLOGI(" name: \"%{public}s\"\n", identifier.name.c_str());
1373 DHLOGI(" physicalPath: \"%{public}s\"\n", identifier.physicalPath.c_str());
1374 DHLOGI(" unique id: \"%{public}s\"\n", identifier.uniqueId.c_str());
1375 DHLOGI(" descriptor: \"%{public}s\"\n", GetAnonyString(identifier.descriptor).c_str());
1376 }
1377 }
1378
RecordChangeEventLog(const RawEvent & event)1379 void InputHub::RecordChangeEventLog(const RawEvent &event)
1380 {
1381 std::string eventType = "";
1382 switch (event.type) {
1383 case EV_KEY:
1384 eventType = "EV_KEY";
1385 break;
1386 case EV_REL:
1387 eventType = "EV_REL";
1388 break;
1389 case EV_ABS:
1390 eventType = "EV_ABS";
1391 break;
1392 case EV_SYN:
1393 eventType = "EV_SYN";
1394 break;
1395 default:
1396 eventType = "other type " + std::to_string(event.type);
1397 break;
1398 }
1399 DHLOGI("0.E2E-Test Sink collect change event, EventType: %{public}s, Code: %{public}d, Value: %{public}d, "
1400 "Path: %{public}s, descriptor: %{public}s, When: %{public}" PRId64 "", eventType.c_str(), event.code,
1401 event.value, event.path.c_str(), GetAnonyString(event.descriptor).c_str(), event.when);
1402 }
1403
RecordEventLog(const RawEvent * event)1404 void InputHub::RecordEventLog(const RawEvent *event)
1405 {
1406 std::string eventType = "";
1407 switch (event->type) {
1408 case EV_KEY:
1409 eventType = "EV_KEY";
1410 break;
1411 case EV_REL:
1412 eventType = "EV_REL";
1413 break;
1414 case EV_ABS:
1415 eventType = "EV_ABS";
1416 break;
1417 case EV_SYN:
1418 eventType = "EV_SYN";
1419 break;
1420 default:
1421 eventType = "other type " + std::to_string(event->type);
1422 break;
1423 }
1424 DHLOGD("1.E2E-Test Sink collect event, EventType: %{public}s, Code: %{public}d, Value: %{public}d, "
1425 "Path: %{public}s, descriptor: %{public}s, When: %{public}" PRId64 "", eventType.c_str(), event->code,
1426 event->value, event->path.c_str(), GetAnonyString(event->descriptor).c_str(), event->when);
1427 }
1428
HandleTouchScreenEvent(struct input_event readBuffer[],const size_t count,std::vector<bool> & needFilted)1429 void InputHub::HandleTouchScreenEvent(struct input_event readBuffer[], const size_t count,
1430 std::vector<bool> &needFilted)
1431 {
1432 std::vector<std::pair<size_t, size_t>> absIndexs;
1433 int32_t firstIndex = -1;
1434 int32_t lastIndex = -1;
1435
1436 for (size_t i = 0; i < count; i++) {
1437 struct input_event& iev = readBuffer[i];
1438 if ((iev.type == EV_ABS) && (iev.code == ABS_X || iev.code == ABS_MT_POSITION_X)) {
1439 firstIndex = static_cast<int32_t>(i);
1440 } else if (iev.type == EV_SYN) {
1441 lastIndex = static_cast<int32_t>(i);
1442 }
1443 if ((firstIndex >= 0) && (lastIndex > firstIndex)) {
1444 absIndexs.emplace_back(std::make_pair((size_t)firstIndex, (size_t)lastIndex));
1445 }
1446 }
1447
1448 AbsInfo absInfo = {
1449 .absX = 0,
1450 .absY = 0,
1451 .absXIndex = -1,
1452 .absYIndex = -1,
1453 };
1454 for (auto iter : absIndexs) {
1455 absInfo.absXIndex = -1;
1456 absInfo.absYIndex = -1;
1457
1458 for (size_t j = iter.first; j <= iter.second; j++) {
1459 struct input_event &iev = readBuffer[j];
1460 if (iev.code == ABS_X || iev.code == ABS_MT_POSITION_X) {
1461 absInfo.absX = static_cast<uint32_t>(iev.value);
1462 absInfo.absXIndex = static_cast<int32_t>(j);
1463 }
1464 if (iev.code == ABS_Y || iev.code == ABS_MT_POSITION_Y) {
1465 absInfo.absY = static_cast<uint32_t>(iev.value);
1466 absInfo.absYIndex = static_cast<int32_t>(j);
1467 }
1468 }
1469
1470 if ((absInfo.absXIndex < 0) || (absInfo.absYIndex < 0)) {
1471 for (size_t j = iter.first; j <= iter.second; j++) {
1472 needFilted[j] = true;
1473 }
1474 continue;
1475 }
1476 if (!CheckTouchPointRegion(readBuffer, absInfo)) {
1477 for (size_t j = iter.first; j <= iter.second; j++) {
1478 needFilted[j] = true;
1479 }
1480 }
1481 }
1482 }
1483
CheckTouchPointRegion(struct input_event readBuffer[],const AbsInfo & absInfo)1484 bool InputHub::CheckTouchPointRegion(struct input_event readBuffer[], const AbsInfo &absInfo)
1485 {
1486 auto sinkInfos = DInputContext::GetInstance().GetAllSinkScreenInfo();
1487
1488 for (const auto &[id, sinkInfo] : sinkInfos) {
1489 auto info = sinkInfo.transformInfo;
1490 if ((absInfo.absX >= info.sinkWinPhyX) && (absInfo.absX <= (info.sinkWinPhyX + info.sinkProjPhyWidth))
1491 && (absInfo.absY >= info.sinkWinPhyY) && (absInfo.absY <= (info.sinkWinPhyY + info.sinkProjPhyHeight))) {
1492 touchDescriptor = sinkInfo.srcScreenInfo.sourcePhyId;
1493 readBuffer[absInfo.absXIndex].value = (absInfo.absX - info.sinkWinPhyX) * info.coeffWidth;
1494 readBuffer[absInfo.absYIndex].value = (absInfo.absY - info.sinkWinPhyY) * info.coeffHeight;
1495 return true;
1496 }
1497 }
1498 return false;
1499 }
1500
CollectTargetDevices()1501 std::vector<InputHub::Device*> InputHub::CollectTargetDevices()
1502 {
1503 std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1504 std::vector<InputHub::Device*> tarVec;
1505 for (const auto &dev : devices_) {
1506 if (((dev.second->classes & INPUT_DEVICE_CLASS_TOUCH) != 0) ||
1507 ((dev.second->classes & INPUT_DEVICE_CLASS_TOUCH_MT) != 0) ||
1508 ((dev.second->classes & INPUT_DEVICE_CLASS_CURSOR) != 0) ||
1509 ((dev.second->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0)) {
1510 DHLOGI("Find target devs need check stat, path: %{public}s, name: %{public}s",
1511 dev.first.c_str(), dev.second->identifier.name.c_str());
1512 tarVec.push_back(dev.second.get());
1513 }
1514 }
1515
1516 return tarVec;
1517 }
1518
SavePressedKeyState(const InputHub::Device * dev,int32_t keyCode)1519 void InputHub::SavePressedKeyState(const InputHub::Device *dev, int32_t keyCode)
1520 {
1521 struct RawEvent event = {
1522 .type = EV_KEY,
1523 .code = keyCode,
1524 .value = KEY_DOWN_STATE,
1525 .descriptor = dev->identifier.descriptor,
1526 .path = dev->path
1527 };
1528 DInputSinkState::GetInstance().AddKeyDownState(event);
1529 DHLOGI("Find Pressed key: %{public}d, device path: %{public}s, dhId: %{public}s", keyCode, dev->path.c_str(),
1530 GetAnonyString(dev->identifier.descriptor).c_str());
1531 }
1532
IsLengthExceeds(const unsigned long * keyState,const unsigned long len,int keyIndex)1533 bool InputHub::IsLengthExceeds(const unsigned long *keyState, const unsigned long len, int keyIndex)
1534 {
1535 if (len < (keyIndex / LONG_BITS) + 1) {
1536 DHLOGE("Length exceeds for key index: %{public}d", keyIndex);
1537 return true;
1538 }
1539 return false;
1540 }
1541
CheckTargetKeyState(const InputHub::Device * dev,const unsigned long * keyState,const unsigned long len)1542 void InputHub::CheckTargetKeyState(const InputHub::Device *dev, const unsigned long *keyState, const unsigned long len)
1543 {
1544 // If device is a mouse, record the mouse pressed key.
1545 if ((dev->classes & INPUT_DEVICE_CLASS_CURSOR) != 0) {
1546 if (IsLengthExceeds(keyState, len, BTN_LEFT)) {
1547 return;
1548 }
1549 int mouseLeftBtnState = BitIsSet(keyState, BTN_LEFT);
1550 if (mouseLeftBtnState != 0) {
1551 SavePressedKeyState(dev, BTN_LEFT);
1552 }
1553 if (IsLengthExceeds(keyState, len, BTN_RIGHT)) {
1554 return;
1555 }
1556 int mouseRightBtnState = BitIsSet(keyState, BTN_RIGHT);
1557 if (mouseRightBtnState != 0) {
1558 SavePressedKeyState(dev, BTN_RIGHT);
1559 }
1560 if (IsLengthExceeds(keyState, len, BTN_MIDDLE)) {
1561 return;
1562 }
1563 int mouseMidBtnState = BitIsSet(keyState, BTN_MIDDLE);
1564 if (mouseMidBtnState != 0) {
1565 SavePressedKeyState(dev, BTN_MIDDLE);
1566 }
1567 }
1568
1569 // If device is a keyboard, record all the pressed keys.
1570 if ((dev->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) {
1571 for (int32_t keyIndex = 0; keyIndex < KEY_MAX; keyIndex++) {
1572 if (IsLengthExceeds(keyState, len, keyIndex)) {
1573 return;
1574 }
1575 if (BitIsSet(keyState, keyIndex) != 0) {
1576 SavePressedKeyState(dev, keyIndex);
1577 }
1578 }
1579 }
1580
1581 // If device is a touchscreen or touchpad, record the touch event.
1582 if ((dev->classes & INPUT_DEVICE_CLASS_TOUCH) != 0 || (dev->classes & INPUT_DEVICE_CLASS_TOUCH_MT) != 0) {
1583 if (IsLengthExceeds(keyState, len, BTN_TOUCH)) {
1584 return;
1585 }
1586 int btnTouchState = BitIsSet(keyState, BTN_TOUCH);
1587 if (btnTouchState != 0) {
1588 SavePressedKeyState(dev, BTN_TOUCH);
1589 }
1590 }
1591 }
1592
1593
CheckTargetDevicesState(std::vector<InputHub::Device * > targetDevices)1594 void InputHub::CheckTargetDevicesState(std::vector<InputHub::Device*> targetDevices)
1595 {
1596 uint32_t count = 0;
1597 unsigned long keyState[NLONGS(KEY_CNT)] = { 0 };
1598 for (const auto *dev : targetDevices) {
1599 while (true) {
1600 if (count > READ_RETRY_MAX) {
1601 break;
1602 }
1603 // Query all key state
1604 int rc = ioctl(dev->fd, EVIOCGKEY(sizeof(keyState)), keyState);
1605 if (rc < 0) {
1606 DHLOGE("read all key state failed, rc=%{public}d", rc);
1607 count += 1;
1608 std::this_thread::sleep_for(std::chrono::milliseconds(READ_SLEEP_TIME_MS));
1609 continue;
1610 }
1611 CheckTargetKeyState(dev, keyState, NLONGS(KEY_CNT));
1612 break;
1613 }
1614 }
1615 }
1616
RecordDeviceStates()1617 void InputHub::RecordDeviceStates()
1618 {
1619 DHLOGI("Start Record keys states");
1620 ScanAndRecordInputDevices();
1621 std::vector<InputHub::Device*> tarDevices = CollectTargetDevices();
1622 DHLOGI("Check target states device num: %{public}zu", tarDevices.size());
1623 CheckTargetDevicesState(tarDevices);
1624 DHLOGI("Finish Record Keys states");
1625 }
1626
ClearDeviceStates()1627 void InputHub::ClearDeviceStates()
1628 {
1629 DHLOGI("Clear Device state");
1630 DInputSinkState::GetInstance().ClearDeviceStates();
1631 }
1632
ClearSkipDevicePaths()1633 void InputHub::ClearSkipDevicePaths()
1634 {
1635 DHLOGI("Clear Skip device path");
1636 std::lock_guard<std::mutex> lock(skipDevicePathsMutex_);
1637 skipDevicePaths_.clear();
1638 }
1639
Device(int fd,const std::string & path)1640 InputHub::Device::Device(int fd, const std::string &path)
1641 : next(nullptr), fd(fd), path(path), identifier({}), classes(0), enabled(false),
1642 isShare(false), isVirtual(fd < 0) {
1643 // Figure out the kinds of events the device reports.
1644 DHLOGI("Ctor Device for get event mask, fd: %{public}d, path: %{public}s", fd, path.c_str());
1645 ioctl(fd, EVIOCGBIT(0, sizeof(evBitmask)), evBitmask);
1646 ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keyBitmask)), keyBitmask);
1647 ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absBitmask)), absBitmask);
1648 ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relBitmask)), relBitmask);
1649 }
1650
~Device()1651 InputHub::Device::~Device()
1652 {
1653 Close();
1654 }
1655
Close()1656 void InputHub::Device::Close()
1657 {
1658 if (fd >= 0) {
1659 ::close(fd);
1660 fd = UN_INIT_FD_VALUE;
1661 }
1662 }
1663
Enable()1664 int32_t InputHub::Device::Enable()
1665 {
1666 char canonicalPath[PATH_MAX + 1] = {0x00};
1667
1668 if (path.length() == 0 || path.length() > PATH_MAX || realpath(path.c_str(), canonicalPath) == nullptr) {
1669 DHLOGE("path check fail, error path: %{public}s", path.c_str());
1670 return ERR_DH_INPUT_HUB_DEVICE_ENABLE_FAIL;
1671 }
1672 fd = open(canonicalPath, O_RDWR | O_CLOEXEC | O_NONBLOCK);
1673 if (fd < 0) {
1674 DHLOGE("could not open %{public}s, %{public}s\n", path.c_str(), ConvertErrNo().c_str());
1675 return ERR_DH_INPUT_HUB_DEVICE_ENABLE_FAIL;
1676 }
1677 enabled = true;
1678 return DH_SUCCESS;
1679 }
1680
Disable()1681 int32_t InputHub::Device::Disable()
1682 {
1683 Close();
1684 enabled = false;
1685 return DH_SUCCESS;
1686 }
1687
HasValidFd() const1688 bool InputHub::Device::HasValidFd() const
1689 {
1690 return !isVirtual && enabled;
1691 }
1692 } // namespace DistributedInput
1693 } // namespace DistributedHardware
1694 } // namespace OHOS
1695