1 /*
2 * Copyright (c) 2021-2023 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 <unistd.h>
29 #include <utility>
30
31 #include "constants_dinput.h"
32 #include "dinput_context.h"
33 #include "dinput_errcode.h"
34 #include "dinput_log.h"
35 #include "dinput_utils_tool.h"
36
37 namespace OHOS {
38 namespace DistributedHardware {
39 namespace DistributedInput {
40 namespace {
41 const uint32_t SLEEP_TIME_US = 100 * 1000;
42 }
43
InputHub()44 InputHub::InputHub() : epollFd_(0), iNotifyFd_(0), inputWd_(0), needToScanDevices_(true), nextDeviceId_(1),
45 mPendingEventItems{}, pendingEventCount_(0), pendingEventIndex_(0), pendingINotify_(false), deviceChanged_(false),
46 inputTypes_(0), isStartCollectEvent_(false), isStartCollectHandler_(false)
47 {
48 Initialize();
49 }
50
~InputHub()51 InputHub::~InputHub()
52 {
53 Release();
54 }
55
Initialize()56 int32_t InputHub::Initialize()
57 {
58 epollFd_ = epoll_create1(EPOLL_CLOEXEC);
59 if (epollFd_ < 0) {
60 DHLOGE("Could not create epoll instance: %s", ConvertErrNo().c_str());
61 return ERR_DH_INPUT_HUB_EPOLL_INIT_FAIL;
62 }
63
64 iNotifyFd_ = inotify_init();
65 inputWd_ = inotify_add_watch(iNotifyFd_, DEVICE_PATH, IN_DELETE | IN_CREATE);
66 if (inputWd_ < 0) {
67 DHLOGE(
68 "Could not register INotify for %s: %s", DEVICE_PATH, ConvertErrNo().c_str());
69 return ERR_DH_INPUT_HUB_EPOLL_INIT_FAIL;
70 }
71
72 struct epoll_event eventItem = {};
73 eventItem.events = EPOLLIN;
74 eventItem.data.fd = iNotifyFd_;
75 int result = epoll_ctl(epollFd_, EPOLL_CTL_ADD, iNotifyFd_, &eventItem);
76 if (result != 0) {
77 DHLOGE("Could not add INotify to epoll instance. errno=%d", errno);
78 return ERR_DH_INPUT_HUB_EPOLL_INIT_FAIL;
79 }
80
81 return DH_SUCCESS;
82 }
83
Release()84 int32_t InputHub::Release()
85 {
86 CloseAllDevicesLocked();
87
88 ::close(epollFd_);
89 ::close(iNotifyFd_);
90 StopCollectInputEvents();
91 StopCollectInputHandler();
92 sharedDHIds_.clear();
93 return DH_SUCCESS;
94 }
95
StartCollectInputEvents(RawEvent * buffer,size_t bufferSize)96 size_t InputHub::StartCollectInputEvents(RawEvent *buffer, size_t bufferSize)
97 {
98 size_t count = 0;
99 isStartCollectEvent_ = true;
100 while (isStartCollectEvent_) {
101 if (needToScanDevices_) {
102 needToScanDevices_ = false;
103 ScanInputDevices(DEVICE_PATH);
104 }
105 {
106 std::unique_lock<std::mutex> deviceLock(devicesMutex_);
107 while (!openingDevices_.empty()) {
108 std::unique_ptr<Device> device = std::move(*openingDevices_.rbegin());
109 openingDevices_.pop_back();
110 DHLOGI("Reporting device opened: id=%s, name=%s\n",
111 GetAnonyInt32(device->id).c_str(), device->path.c_str());
112 auto [dev_it, inserted] = devices_.insert_or_assign(device->id, std::move(device));
113 if (!inserted) {
114 DHLOGI("Device id %s exists, replaced. \n", GetAnonyInt32(device->id).c_str());
115 }
116 }
117 }
118
119 deviceChanged_ = false;
120 count = GetEvents(buffer, bufferSize);
121 // readNotify() will modify the list of devices so this must be done after
122 // processing all other events to ensure that we read all remaining events
123 // before closing the devices.
124 if (pendingINotify_ && pendingEventIndex_ >= pendingEventCount_) {
125 pendingINotify_ = false;
126 ReadNotifyLocked();
127 deviceChanged_ = true;
128 }
129
130 // Report added or removed devices immediately.
131 if (deviceChanged_) {
132 continue;
133 }
134
135 if (count > 0) {
136 break;
137 }
138
139 if (RefreshEpollItem(false) < 0) {
140 break;
141 }
142 }
143
144 // All done, return the number of events we read.
145 return count;
146 }
147
StopCollectInputEvents()148 void InputHub::StopCollectInputEvents()
149 {
150 DHLOGI("Stop Collect Input Events Thread");
151 isStartCollectEvent_ = false;
152 }
153
GetEvents(RawEvent * buffer,size_t bufferSize)154 size_t InputHub::GetEvents(RawEvent *buffer, size_t bufferSize)
155 {
156 RawEvent* event = buffer;
157 size_t capacity = bufferSize;
158 while (pendingEventIndex_ < pendingEventCount_) {
159 std::unique_lock<std::mutex> my_lock(operationMutex_);
160 const struct epoll_event& eventItem = mPendingEventItems[pendingEventIndex_++];
161 if (eventItem.data.fd == iNotifyFd_) {
162 if (eventItem.events & EPOLLIN) {
163 pendingINotify_ = true;
164 } else {
165 DHLOGI("Received no epoll event 0x%08x.", eventItem.events);
166 }
167 continue;
168 }
169 struct input_event readBuffer[bufferSize];
170 int32_t readSize = read(eventItem.data.fd, readBuffer, sizeof(struct input_event) * capacity);
171 size_t count = ReadInputEvent(readSize, *GetDeviceByFdLocked(eventItem.data.fd));
172 Device* device = GetSupportDeviceByFd(eventItem.data.fd);
173 if (!device) {
174 continue;
175 }
176 if (!sharedDHIds_[device->identifier.descriptor]) {
177 continue;
178 }
179 DHLOGD("shared device dhId: %s, name: %s", GetAnonyString(device->identifier.descriptor).c_str(),
180 device->identifier.name.c_str());
181 if (eventItem.events & EPOLLIN) {
182 event += CollectEvent(event, capacity, device, readBuffer, count);
183
184 if (capacity == 0) {
185 pendingEventIndex_ -= 1;
186 break;
187 }
188 } else if (eventItem.events & EPOLLHUP) {
189 DHLOGI("Removing device %s due to epoll hang-up event.", device->identifier.name.c_str());
190 deviceChanged_ = true;
191 CloseDeviceLocked(*device);
192 }
193 }
194 return event - buffer;
195 }
196
IsTouchPad(const InputDevice & inputDevice)197 bool InputHub::IsTouchPad(const InputDevice &inputDevice)
198 {
199 std::string dhName = inputDevice.name;
200 DHLOGI("device name is %s.", dhName.c_str());
201 transform(dhName.begin(), dhName.end(), dhName.begin(), ::tolower);
202 if (dhName.find(DH_TOUCH_PAD) == std::string::npos) {
203 return false;
204 }
205 return true;
206 }
207
CollectEvent(RawEvent * buffer,size_t & capacity,Device * device,struct input_event readBuffer[],const size_t count)208 size_t InputHub::CollectEvent(RawEvent *buffer, size_t &capacity, Device *device, struct input_event readBuffer[],
209 const size_t count)
210 {
211 std::vector<bool> needFilted(capacity, false);
212 bool isTouchEvent = false;
213 if ((device->classes & INPUT_DEVICE_CLASS_TOUCH_MT) || (device->classes & INPUT_DEVICE_CLASS_TOUCH)) {
214 if (!IsTouchPad(device->identifier)) {
215 isTouchEvent = true;
216 HandleTouchScreenEvent(readBuffer, count, needFilted);
217 }
218 }
219
220 RawEvent* event = buffer;
221 for (size_t i = 0; i < count; i++) {
222 if (needFilted[i]) {
223 continue;
224 }
225 const struct input_event& iev = readBuffer[i];
226 event->when = ProcessEventTimestamp(iev);
227 event->type = iev.type;
228 event->code = iev.code;
229 event->value = iev.value;
230 event->path = device->path;
231 event->descriptor = isTouchEvent ? touchDescriptor : device->identifier.descriptor;
232 RecordEventLog(event);
233 event += 1;
234 capacity -= 1;
235 }
236 return event - buffer;
237 }
238
ReadInputEvent(int32_t readSize,Device & device)239 size_t InputHub::ReadInputEvent(int32_t readSize, Device &device)
240 {
241 size_t count = 0;
242 if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
243 // Device was removed before INotify noticed.
244 DHLOGE("could not get event, removed? (fd: %d size: %d"
245 " errno: %d)\n",
246 device.fd, readSize, errno);
247 deviceChanged_ = true;
248 CloseDeviceLocked(device);
249 } else if (readSize < 0) {
250 if (errno != EAGAIN && errno != EINTR) {
251 DHLOGW("could not get event (errno=%d)", errno);
252 }
253 } else if ((readSize % sizeof(struct input_event)) != 0) {
254 DHLOGW("could not get event (wrong size: %d)", readSize);
255 } else {
256 count = size_t(readSize) / sizeof(struct input_event);
257 return count;
258 }
259 return count;
260 }
261
DeviceIsExists(InputDeviceEvent * buffer,size_t bufferSize)262 size_t InputHub::DeviceIsExists(InputDeviceEvent *buffer, size_t bufferSize)
263 {
264 InputDeviceEvent* event = buffer;
265 size_t capacity = bufferSize;
266 // Report any devices that had last been added/removed.
267 {
268 std::unique_lock<std::mutex> deviceLock(devicesMutex_);
269 for (auto it = closingDevices_.begin(); it != closingDevices_.end();) {
270 std::unique_ptr<Device> device = std::move(*it);
271 DHLOGI("Reporting device closed: id=%s, name=%s\n",
272 GetAnonyInt32(device->id).c_str(), device->path.c_str());
273 event->type = DeviceType::DEVICE_REMOVED;
274 event->deviceInfo = device->identifier;
275 event += 1;
276 it = closingDevices_.erase(it);
277 if (capacity == 0) {
278 break;
279 }
280 capacity--;
281 }
282 }
283
284 if (needToScanDevices_) {
285 needToScanDevices_ = false;
286 ScanInputDevices(DEVICE_PATH);
287 }
288
289 {
290 std::unique_lock<std::mutex> deviceLock(devicesMutex_);
291 while (!openingDevices_.empty()) {
292 std::unique_ptr<Device> device = std::move(*openingDevices_.rbegin());
293 openingDevices_.pop_back();
294 DHLOGI("Reporting device opened: id=%s, name=%s\n",
295 GetAnonyInt32(device->id).c_str(), device->path.c_str());
296 event->type = DeviceType::DEVICE_ADDED;
297 event->deviceInfo = device->identifier;
298 event += 1;
299
300 auto [dev_it, inserted] = devices_.insert_or_assign(device->id, std::move(device));
301 if (!inserted) {
302 DHLOGI("Device id %s exists, replaced. \n", GetAnonyInt32(device->id).c_str());
303 }
304 if (capacity == 0) {
305 break;
306 }
307 capacity--;
308 }
309 }
310 return event - buffer;
311 }
312
StartCollectInputHandler(InputDeviceEvent * buffer,size_t bufferSize)313 size_t InputHub::StartCollectInputHandler(InputDeviceEvent *buffer, size_t bufferSize)
314 {
315 size_t count = 0;
316 isStartCollectHandler_ = true;
317 while (isStartCollectHandler_) {
318 count = DeviceIsExists(buffer, bufferSize);
319 deviceChanged_ = false;
320 GetDeviceHandler();
321
322 if (pendingINotify_ && pendingEventIndex_ >= pendingEventCount_) {
323 pendingINotify_ = false;
324 ReadNotifyLocked();
325 deviceChanged_ = true;
326 }
327
328 // Report added or removed devices immediately.
329 if (deviceChanged_) {
330 continue;
331 }
332 if (count > 0) {
333 break;
334 }
335 if (RefreshEpollItem(true) < 0) {
336 break;
337 }
338 }
339
340 // All done, return the number of events we read.
341 return count;
342 }
343
StopCollectInputHandler()344 void InputHub::StopCollectInputHandler()
345 {
346 DHLOGI("Stop Collect Input Handler Thread");
347 isStartCollectHandler_ = false;
348 }
349
GetDeviceHandler()350 void InputHub::GetDeviceHandler()
351 {
352 while (pendingEventIndex_ < pendingEventCount_) {
353 std::unique_lock<std::mutex> my_lock(operationMutex_);
354 const struct epoll_event& eventItem = mPendingEventItems[pendingEventIndex_++];
355 if (eventItem.data.fd == iNotifyFd_) {
356 if (eventItem.events & EPOLLIN) {
357 pendingINotify_ = true;
358 } else {
359 DHLOGI(
360 "Received unexpected epoll event 0x%08x for INotify.", eventItem.events);
361 }
362 continue;
363 }
364
365 Device* device = GetDeviceByFdLocked(eventItem.data.fd);
366 if (!device) {
367 DHLOGE(
368 "Received unexpected epoll event 0x%08x for unknown fd %d.",
369 eventItem.events, eventItem.data.fd);
370 continue;
371 }
372
373 if (eventItem.events & EPOLLHUP) {
374 DHLOGI("Removing device %s due to epoll hang-up event.",
375 device->identifier.name.c_str());
376 deviceChanged_ = true;
377 CloseDeviceLocked(*device);
378 }
379 }
380 }
381
RefreshEpollItem(bool isSleep)382 int32_t InputHub::RefreshEpollItem(bool isSleep)
383 {
384 pendingEventIndex_ = 0;
385 int pollResult = epoll_wait(epollFd_, mPendingEventItems, EPOLL_MAX_EVENTS, EPOLL_WAITTIME);
386 if (pollResult == 0) {
387 // Timed out.
388 pendingEventCount_ = 0;
389 return ERR_DH_INPUT_HUB_EPOLL_WAIT_TIMEOUT;
390 }
391
392 if (pollResult < 0) {
393 // An error occurred.
394 pendingEventCount_ = 0;
395
396 // Sleep after errors to avoid locking up the system.
397 // Hopefully the error is transient.
398 if (errno != EINTR) {
399 DHLOGE("poll failed (errno=%d)\n", errno);
400 usleep(SLEEP_TIME_US);
401 }
402 } else {
403 // Some events occurred.
404 pendingEventCount_ = pollResult;
405 }
406 if (isSleep) {
407 usleep(SLEEP_TIME_US);
408 }
409 return DH_SUCCESS;
410 }
411
GetAllInputDevices()412 std::vector<InputDevice> InputHub::GetAllInputDevices()
413 {
414 std::unique_lock<std::mutex> deviceLock(devicesMutex_);
415 std::vector<InputDevice> vecDevice;
416 for (const auto& [id, device] : devices_) {
417 vecDevice.push_back(device->identifier);
418 }
419 return vecDevice;
420 }
421
ScanInputDevices(const std::string & dirName)422 void InputHub::ScanInputDevices(const std::string &dirName)
423 {
424 DHLOGI("ScanInputDevices enter, dirName %s.", dirName.c_str());
425 std::vector<std::string> vecInputDevPath;
426 ScanInputDevicesPath(dirName, vecInputDevPath);
427 for (const auto &tempPath: vecInputDevPath) {
428 OpenInputDeviceLocked(tempPath);
429 }
430 }
431
IsDeviceRegistered(const std::string & devicePath)432 bool InputHub::IsDeviceRegistered(const std::string &devicePath)
433 {
434 std::unique_lock<std::mutex> deviceLock(devicesMutex_);
435 for (const auto& [deviceId, device] : devices_) {
436 if (device->path == devicePath) {
437 return true; // device was already registered
438 }
439 }
440 return false;
441 }
442
OpenInputDeviceLocked(const std::string & devicePath)443 int32_t InputHub::OpenInputDeviceLocked(const std::string &devicePath)
444 {
445 if (IsDeviceRegistered(devicePath)) {
446 return DH_SUCCESS;
447 }
448
449 std::unique_lock<std::mutex> my_lock(operationMutex_);
450 DHLOGI("Opening device: %s", devicePath.c_str());
451 int fd = OpenInputDeviceFdByPath(devicePath);
452 if (fd == UN_INIT_FD_VALUE) {
453 DHLOGE("The fd open failed, devicePath %s.", devicePath.c_str());
454 return ERR_DH_INPUT_HUB_OPEN_DEVICEPATH_FAIL;
455 }
456
457 InputDevice identifier;
458 if (QueryInputDeviceInfo(fd, identifier) < 0) {
459 CloseFd(fd);
460 return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
461 }
462 GenerateDescriptor(identifier);
463
464 // Allocate device. (The device object takes ownership of the fd at this point.)
465 int32_t deviceId = nextDeviceId_++;
466 std::unique_ptr<Device> device = std::make_unique<Device>(fd, deviceId, devicePath, identifier);
467 RecordDeviceLog(deviceId, devicePath, identifier);
468
469 if (MakeDevice(fd, std::move(device)) < 0) {
470 CloseFd(fd);
471 return ERR_DH_INPUT_HUB_MAKE_DEVICE_FAIL;
472 }
473
474 return DH_SUCCESS;
475 }
476
QueryInputDeviceInfo(int fd,InputDevice & identifier)477 int32_t InputHub::QueryInputDeviceInfo(int fd, InputDevice &identifier)
478 {
479 char buffer[INPUT_EVENT_BUFFER_SIZE] = {0};
480 // Get device name.
481 if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
482 DHLOGE(
483 "Could not get device name for %s", ConvertErrNo().c_str());
484 } else {
485 buffer[sizeof(buffer) - 1] = '\0';
486 identifier.name = buffer;
487 }
488 DHLOGD("QueryInputDeviceInfo deviceName: %s", buffer);
489 // If the device is already a virtual device, don't monitor it.
490 if (identifier.name.find(VIRTUAL_DEVICE_NAME) != std::string::npos) {
491 return ERR_DH_INPUT_HUB_IS_VIRTUAL_DEVICE;
492 }
493 // Get device driver version.
494 int driverVersion;
495 if (ioctl(fd, EVIOCGVERSION, &driverVersion)) {
496 DHLOGE("could not get driver version for %s\n", ConvertErrNo().c_str());
497 return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
498 }
499 // Get device identifier.
500 struct input_id inputId;
501 if (ioctl(fd, EVIOCGID, &inputId)) {
502 DHLOGE("could not get device input id for %s\n", ConvertErrNo().c_str());
503 return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
504 }
505 identifier.bus = inputId.bustype;
506 identifier.product = inputId.product;
507 identifier.vendor = inputId.vendor;
508 identifier.version = inputId.version;
509 // Get device physical physicalPath.
510 if (ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
511 DHLOGE("could not get physicalPath for %s\n", ConvertErrNo().c_str());
512 } else {
513 buffer[sizeof(buffer) - 1] = '\0';
514 identifier.physicalPath = buffer;
515 }
516 // Get device unique id.
517 if (ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
518 DHLOGE("could not get idstring for %s\n", ConvertErrNo().c_str());
519 } else {
520 buffer[sizeof(buffer) - 1] = '\0';
521 identifier.uniqueId = buffer;
522 }
523
524 QueryEventInfo(fd, identifier);
525 return DH_SUCCESS;
526 }
527
QueryEventInfo(int fd,InputDevice & identifier)528 void InputHub::QueryEventInfo(int fd, InputDevice &identifier)
529 {
530 DHLOGI("QueryEventInfo: devName: %s, dhId: %s!", identifier.name.c_str(),
531 GetAnonyString(identifier.descriptor).c_str());
532 struct libevdev *dev = GetLibEvDev(fd);
533 if (dev == nullptr) {
534 DHLOGE("dev is nullptr");
535 return;
536 }
537 GetEventTypes(dev, identifier);
538 GetEventKeys(dev, identifier);
539 GetABSInfo(dev, identifier);
540 GetRELTypes(dev, identifier);
541 GetProperties(dev, identifier);
542 libevdev_free(dev);
543 }
544
GetLibEvDev(int fd)545 struct libevdev* InputHub::GetLibEvDev(int fd)
546 {
547 struct libevdev *dev = nullptr;
548 int rc = 1;
549 rc = libevdev_new_from_fd(fd, &dev);
550 if (rc < 0) {
551 DHLOGE("Failed to init libevdev (%s)", strerror(-rc));
552 return nullptr;
553 }
554 return dev;
555 }
556
GetEventTypes(struct libevdev * dev,InputDevice & identifier)557 void InputHub::GetEventTypes(struct libevdev *dev, InputDevice &identifier)
558 {
559 for (uint32_t eventType = 0; eventType < EV_CNT; eventType++) {
560 if (!libevdev_has_event_type(dev, eventType)) {
561 DHLOGD("The device is not support eventType: %d", eventType);
562 continue;
563 }
564 DHLOGI("QueryInputDeviceInfo eventType: %d", eventType);
565 identifier.eventTypes.push_back(eventType);
566 }
567 }
568
GetEventKeys(struct libevdev * dev,InputDevice & identifier)569 int32_t InputHub::GetEventKeys(struct libevdev *dev, InputDevice &identifier)
570 {
571 if (!libevdev_has_event_type(dev, EV_KEY)) {
572 DHLOGE("The device doesn't has EV_KEY type!");
573 return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
574 }
575 for (uint32_t eventKey = 0; eventKey < KEY_CNT; eventKey++) {
576 if (!libevdev_has_event_code(dev, EV_KEY, eventKey)) {
577 DHLOGD("The device is not support eventKey: %d", eventKey);
578 continue;
579 }
580 DHLOGI("QueryInputDeviceInfo eventKey: %d", eventKey);
581 identifier.eventKeys.push_back(eventKey);
582 }
583 return DH_SUCCESS;
584 }
585
GetABSInfo(struct libevdev * dev,InputDevice & identifier)586 int32_t InputHub::GetABSInfo(struct libevdev *dev, InputDevice &identifier)
587 {
588 if (!libevdev_has_event_type(dev, EV_ABS)) {
589 DHLOGE("The device doesn't has EV_ABS type!");
590 return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
591 }
592 DHLOGI("The device has abs info, devName: %s, dhId: %s!", identifier.name.c_str(),
593 GetAnonyString(identifier.descriptor).c_str());
594 for (uint32_t absType = 0; absType < ABS_CNT; absType++) {
595 if (!libevdev_has_event_code(dev, EV_ABS, absType)) {
596 DHLOGD("The device is not support absType: %d", absType);
597 continue;
598 }
599 DHLOGI("QueryInputDeviceInfo abs type: %d", absType);
600 identifier.absTypes.push_back(absType);
601 const struct input_absinfo *abs = libevdev_get_abs_info(dev, absType);
602 if (abs == nullptr) {
603 DHLOGE("absInfo is nullptr!");
604 continue;
605 }
606 DHLOGI("QueryInputDeviceInfo abs info value: %d, min: %d, max: %d, fuzz: %d, flat: %d, res: %d", abs->value,
607 abs->minimum, abs->maximum, abs->fuzz, abs->flat, abs->resolution);
608 identifier.absInfos[absType].push_back(abs->value);
609 identifier.absInfos[absType].push_back(abs->minimum);
610 identifier.absInfos[absType].push_back(abs->maximum);
611 identifier.absInfos[absType].push_back(abs->fuzz);
612 identifier.absInfos[absType].push_back(abs->flat);
613 identifier.absInfos[absType].push_back(abs->resolution);
614 }
615 return DH_SUCCESS;
616 }
617
GetRELTypes(struct libevdev * dev,InputDevice & identifier)618 int32_t InputHub::GetRELTypes(struct libevdev *dev, InputDevice &identifier)
619 {
620 if (!libevdev_has_event_type(dev, EV_REL)) {
621 DHLOGE("The device doesn't has EV_REL type!");
622 return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
623 }
624 for (uint32_t code = 0; code < REL_CNT; code++) {
625 if (!libevdev_has_event_code(dev, EV_REL, code)) {
626 DHLOGD("The device is not support eventCode: %d", code);
627 continue;
628 }
629 DHLOGI("QueryInputDeviceInfo rel types: %d", code);
630 identifier.relTypes.push_back(code);
631 }
632 return DH_SUCCESS;
633 }
634
GetProperties(struct libevdev * dev,InputDevice & identifier)635 void InputHub::GetProperties(struct libevdev *dev, InputDevice &identifier)
636 {
637 for (uint32_t prop = 0; prop < INPUT_PROP_CNT; prop++) {
638 if (libevdev_has_property(dev, prop)) {
639 DHLOGI("QueryInputDeviceInfo rel prop: %d", prop);
640 identifier.properties.push_back(prop);
641 }
642 }
643 }
644
MakeDevice(int fd,std::unique_ptr<Device> device)645 int32_t InputHub::MakeDevice(int fd, std::unique_ptr<Device> device)
646 {
647 // Figure out the kinds of events the device reports.
648 ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device->keyBitmask)), device->keyBitmask);
649 ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(device->absBitmask)), device->absBitmask);
650 ioctl(fd, EVIOCGBIT(EV_REL, sizeof(device->relBitmask)), device->relBitmask);
651
652 // See if this is a multi-touch touchscreen device.
653 if (TestBit(BTN_TOUCH, device->keyBitmask) &&
654 TestBit(ABS_MT_POSITION_X, device->absBitmask) &&
655 TestBit(ABS_MT_POSITION_Y, device->absBitmask)) {
656 QueryLocalTouchScreenInfo(fd);
657 device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
658 } else if (TestBit(BTN_TOUCH, device->keyBitmask) &&
659 TestBit(ABS_X, device->absBitmask) &&
660 TestBit(ABS_Y, device->absBitmask)) {
661 QueryLocalTouchScreenInfo(fd);
662 device->classes |= INPUT_DEVICE_CLASS_TOUCH;
663 }
664
665 // See if this is a cursor device such as a trackball or mouse.
666 if (TestBit(BTN_MOUSE, device->keyBitmask)
667 && TestBit(REL_X, device->relBitmask)
668 && TestBit(REL_Y, device->relBitmask)) {
669 device->classes |= INPUT_DEVICE_CLASS_CURSOR;
670 }
671
672 // for Linux version 4.14.116, touchpad recognized as mouse and keyboard at same time,
673 // need to avoid device->classes to be 0x09, which mmi can't handler.
674 // See if this is a keyboard.
675 if (device->classes == 0) {
676 bool haveKeyboardKeys = ContainsNonZeroByte(device->keyBitmask, 0, SizeofBitArray(BTN_MISC));
677 if (haveKeyboardKeys) {
678 device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
679 }
680 }
681
682 // If the device isn't recognized as something we handle, don't monitor it.
683 if (device->classes == 0) {
684 DHLOGI("Dropping device: name='%s'", device->identifier.name.c_str());
685 return ERR_DH_INPUT_HUB_MAKE_DEVICE_FAIL;
686 }
687
688 if (RegisterDeviceForEpollLocked(*device) != DH_SUCCESS) {
689 return ERR_DH_INPUT_HUB_MAKE_DEVICE_FAIL;
690 }
691
692 device->identifier.classes = device->classes;
693
694 DHLOGI("inputType=%d", inputTypes_.load());
695 DHLOGI("New device: fd=%d, name='%s', classes=0x%x", fd, device->identifier.name.c_str(),
696 device->classes);
697
698 AddDeviceLocked(std::move(device));
699 return DH_SUCCESS;
700 }
701
QueryLocalTouchScreenInfo(int fd)702 int32_t InputHub::QueryLocalTouchScreenInfo(int fd)
703 {
704 LocalTouchScreenInfo info = DInputContext::GetInstance().GetLocalTouchScreenInfo();
705
706 InputDevice identifier;
707 if (QueryInputDeviceInfo(fd, identifier) < 0) {
708 return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
709 }
710 identifier.classes |= INPUT_DEVICE_CLASS_TOUCH_MT;
711 info.localAbsInfo.deviceInfo = identifier;
712
713 struct input_absinfo absInfo;
714 ioctl(fd, EVIOCGABS(ABS_MT_POSITION_X), &absInfo);
715 info.localAbsInfo.absXMin = absInfo.minimum;
716 info.localAbsInfo.absXMax = absInfo.maximum;
717 info.localAbsInfo.absMtPositionXMin = absInfo.minimum;
718 info.localAbsInfo.absMtPositionXMax = absInfo.maximum;
719 info.sinkPhyWidth = static_cast<uint32_t>(absInfo.maximum + 1);
720
721 ioctl(fd, EVIOCGABS(ABS_MT_POSITION_Y), &absInfo);
722 info.localAbsInfo.absYMin = absInfo.minimum;
723 info.localAbsInfo.absYMax = absInfo.maximum;
724 info.localAbsInfo.absMtPositionYMin = absInfo.minimum;
725 info.localAbsInfo.absMtPositionYMax = absInfo.maximum;
726 info.sinkPhyHeight = static_cast<uint32_t>(absInfo.maximum + 1);
727
728 ioctl(fd, EVIOCGABS(ABS_PRESSURE), &absInfo);
729 info.localAbsInfo.absPressureMin = absInfo.minimum;
730 info.localAbsInfo.absPressureMax = absInfo.maximum;
731 info.localAbsInfo.absMtPressureMin = absInfo.minimum;
732 info.localAbsInfo.absMtPressureMax = absInfo.maximum;
733
734 ioctl(fd, EVIOCGABS(ABS_MT_TOUCH_MAJOR), &absInfo);
735 info.localAbsInfo.absMtTouchMajorMin = absInfo.minimum;
736 info.localAbsInfo.absMtTouchMajorMax = absInfo.maximum;
737
738 ioctl(fd, EVIOCGABS(ABS_MT_TOUCH_MINOR), &absInfo);
739 info.localAbsInfo.absMtTouchMinorMin = absInfo.minimum;
740 info.localAbsInfo.absMtTouchMinorMax = absInfo.maximum;
741
742 ioctl(fd, EVIOCGABS(ABS_MT_ORIENTATION), &absInfo);
743 info.localAbsInfo.absMtOrientationMin = absInfo.minimum;
744 info.localAbsInfo.absMtOrientationMax = absInfo.maximum;
745
746 ioctl(fd, EVIOCGABS(ABS_MT_BLOB_ID), &absInfo);
747 info.localAbsInfo.absMtBlobIdMin = absInfo.minimum;
748 info.localAbsInfo.absMtBlobIdMax = absInfo.maximum;
749
750 ioctl(fd, EVIOCGABS(ABS_MT_TRACKING_ID), &absInfo);
751 info.localAbsInfo.absMtTrackingIdMin = absInfo.minimum;
752 info.localAbsInfo.absMtTrackingIdMax = absInfo.maximum;
753
754 DInputContext::GetInstance().SetLocalTouchScreenInfo(info);
755 return DH_SUCCESS;
756 }
757
StringPrintf(const char * format,...) const758 std::string InputHub::StringPrintf(const char *format, ...) const
759 {
760 static const int kSpaceLength = 1024;
761 char space[kSpaceLength];
762
763 va_list ap;
764 va_start(ap, format);
765 std::string result;
766 int32_t ret = vsnprintf_s(space, sizeof(space), sizeof(space) - 1, format, ap);
767 if (ret >= DH_SUCCESS && static_cast<size_t>(ret) < sizeof(space)) {
768 result = space;
769 } else {
770 va_end(ap);
771 return "the buffer is overflow!";
772 }
773 va_end(ap);
774 return result;
775 }
776
GenerateDescriptor(InputDevice & identifier) const777 void InputHub::GenerateDescriptor(InputDevice &identifier) const
778 {
779 std::string rawDescriptor;
780 rawDescriptor += StringPrintf(":%04x:%04x:", identifier.vendor,
781 identifier.product);
782 // add handling for USB devices to not uniqueify kbs that show up twice
783 if (!identifier.uniqueId.empty()) {
784 rawDescriptor += "uniqueId:";
785 rawDescriptor += identifier.uniqueId;
786 }
787 if (!identifier.physicalPath.empty()) {
788 rawDescriptor += "physicalPath:";
789 rawDescriptor += identifier.physicalPath;
790 }
791 if (!identifier.name.empty()) {
792 rawDescriptor += "name:";
793 std::string name = identifier.name;
794 rawDescriptor += regex_replace(name, std::regex(" "), "");
795 }
796
797 identifier.descriptor = DH_ID_PREFIX + Sha256(rawDescriptor);
798 DHLOGI("Created descriptor: raw=%s, cooked=%s", rawDescriptor.c_str(),
799 GetAnonyString(identifier.descriptor).c_str());
800 }
801
RegisterDeviceForEpollLocked(const Device & device)802 int32_t InputHub::RegisterDeviceForEpollLocked(const Device &device)
803 {
804 int32_t result = RegisterFdForEpoll(device.fd);
805 if (result != DH_SUCCESS) {
806 DHLOGE("Could not add input device fd to epoll for device %d", device.id);
807 return result;
808 }
809 return result;
810 }
811
RegisterFdForEpoll(int fd)812 int32_t InputHub::RegisterFdForEpoll(int fd)
813 {
814 struct epoll_event eventItem = {};
815 eventItem.events = EPOLLIN | EPOLLWAKEUP;
816 eventItem.data.fd = fd;
817 if (epoll_ctl(epollFd_, EPOLL_CTL_ADD, fd, &eventItem)) {
818 DHLOGE("Could not add fd to epoll instance: %s", ConvertErrNo().c_str());
819 return -errno;
820 }
821 return DH_SUCCESS;
822 }
823
AddDeviceLocked(std::unique_ptr<Device> device)824 void InputHub::AddDeviceLocked(std::unique_ptr<Device> device)
825 {
826 std::unique_lock<std::mutex> deviceLock(devicesMutex_);
827 openingDevices_.push_back(std::move(device));
828 }
829
CloseDeviceLocked(Device & device)830 void InputHub::CloseDeviceLocked(Device &device)
831 {
832 DHLOGI("Removed device: path=%s name=%s id=%s fd=%d classes=0x%x",
833 device.path.c_str(), device.identifier.name.c_str(), GetAnonyInt32(device.id).c_str(),
834 device.fd, device.classes);
835
836 UnregisterDeviceFromEpollLocked(device);
837 device.Close();
838 {
839 std::unique_lock<std::mutex> devicesLock(devicesMutex_);
840 closingDevices_.push_back(std::move(devices_[device.id]));
841 devices_.erase(device.id);
842 }
843 }
844
CloseDeviceForAllLocked(Device & device)845 void InputHub::CloseDeviceForAllLocked(Device &device)
846 {
847 DHLOGI("Removed device: path=%s name=%s id=%s fd=%d classes=0x%x",
848 device.path.c_str(), device.identifier.name.c_str(), GetAnonyInt32(device.id).c_str(),
849 device.fd, device.classes);
850
851 UnregisterDeviceFromEpollLocked(device);
852 device.Close();
853 closingDevices_.push_back(std::move(devices_[device.id]));
854 devices_.erase(device.id);
855 }
856
UnregisterDeviceFromEpollLocked(const Device & device) const857 int32_t InputHub::UnregisterDeviceFromEpollLocked(const Device &device) const
858 {
859 if (device.HasValidFd()) {
860 int32_t result = UnregisterFdFromEpoll(device.fd);
861 if (result != DH_SUCCESS) {
862 DHLOGE("Could not remove input device fd from epoll for device %s",
863 GetAnonyInt32(device.id).c_str());
864 return result;
865 }
866 }
867 return DH_SUCCESS;
868 }
869
UnregisterFdFromEpoll(int fd) const870 int32_t InputHub::UnregisterFdFromEpoll(int fd) const
871 {
872 if (epoll_ctl(epollFd_, EPOLL_CTL_DEL, fd, nullptr)) {
873 DHLOGE("Could not remove fd from epoll instance: %s", ConvertErrNo().c_str());
874 return ERR_DH_INPUT_HUB_UNREGISTER_FD_FAIL;
875 }
876 return DH_SUCCESS;
877 }
878
ReadNotifyLocked()879 int32_t InputHub::ReadNotifyLocked()
880 {
881 size_t res;
882 char eventBuf[512];
883 struct inotify_event *event;
884
885 DHLOGI("readNotify nfd: %d\n", iNotifyFd_);
886 res = static_cast<size_t>(read(iNotifyFd_, eventBuf, sizeof(eventBuf)));
887 if (res < sizeof(*event)) {
888 if (errno == EINTR) {
889 return DH_SUCCESS;
890 }
891 DHLOGE("could not get event, %s\n", ConvertErrNo().c_str());
892 return ERR_DH_INPUT_HUB_GET_EVENT_FAIL;
893 }
894
895 {
896 size_t eventSize = 0;
897 size_t eventPos = 0;
898 while (res >= sizeof(*event)) {
899 event = reinterpret_cast<struct inotify_event *>(eventBuf + eventPos);
900 JudgeDeviceOpenOrClose(*event);
901 eventSize = sizeof(*event) + event->len;
902 res -= eventSize;
903 eventPos += eventSize;
904 }
905 }
906 return DH_SUCCESS;
907 }
908
JudgeDeviceOpenOrClose(const inotify_event & event)909 void InputHub::JudgeDeviceOpenOrClose(const inotify_event &event)
910 {
911 if (event.len) {
912 if (event.wd == inputWd_) {
913 std::string filename = std::string(DEVICE_PATH) + "/" + event.name;
914 if (event.mask & IN_CREATE) {
915 OpenInputDeviceLocked(filename);
916 } else {
917 DHLOGI("Removing device '%s' due to inotify event\n", filename.c_str());
918 CloseDeviceByPathLocked(filename);
919 }
920 } else {
921 DHLOGI("Unexpected inotify event, wd = %i", event.wd);
922 }
923 }
924 }
925
CloseDeviceByPathLocked(const std::string & devicePath)926 void InputHub::CloseDeviceByPathLocked(const std::string &devicePath)
927 {
928 Device* device = GetDeviceByPathLocked(devicePath);
929 if (device) {
930 CloseDeviceLocked(*device);
931 return;
932 }
933 DHLOGI("Remove device: %s not found, device may already have been removed.", devicePath.c_str());
934 }
935
CloseAllDevicesLocked()936 void InputHub::CloseAllDevicesLocked()
937 {
938 DHLOGI("Close All Devices");
939 std::unique_lock<std::mutex> deviceLock(devicesMutex_);
940 while (!devices_.empty()) {
941 CloseDeviceForAllLocked(*(devices_.begin()->second));
942 }
943 }
944
GetDeviceByPathLocked(const std::string & devicePath)945 InputHub::Device* InputHub::GetDeviceByPathLocked(const std::string &devicePath)
946 {
947 std::unique_lock<std::mutex> deviceLock(devicesMutex_);
948 for (const auto& [id, device] : devices_) {
949 if (device->path == devicePath) {
950 return device.get();
951 }
952 }
953 return nullptr;
954 }
955
GetDeviceByFdLocked(int fd)956 InputHub::Device* InputHub::GetDeviceByFdLocked(int fd)
957 {
958 std::unique_lock<std::mutex> deviceLock(devicesMutex_);
959 for (const auto& [id, device] : devices_) {
960 if (device->fd == fd) {
961 return device.get();
962 }
963 }
964 return nullptr;
965 }
966
GetSupportDeviceByFd(int fd)967 InputHub::Device* InputHub::GetSupportDeviceByFd(int fd)
968 {
969 DHLOGI("GetSupportDeviceByFd fd: %d", fd);
970 std::unique_lock<std::mutex> deviceLock(devicesMutex_);
971 for (const auto& [id, device] : devices_) {
972 if (device != nullptr && device->fd == fd) {
973 DHLOGI("GetSupportDeviceByFd device: %d, fd: %d, path: %s, dhId: %s, classes=0x%x", id, device->fd,
974 device->path.c_str(), GetAnonyString(device->identifier.descriptor).c_str(), device->classes);
975 return device.get();
976 }
977 }
978 return nullptr;
979 }
980
ContainsNonZeroByte(const uint8_t * array,uint32_t startIndex,uint32_t endIndex)981 bool InputHub::ContainsNonZeroByte(const uint8_t *array, uint32_t startIndex, uint32_t endIndex)
982 {
983 const uint8_t* end = array + endIndex;
984 array += startIndex;
985 while (array != end) {
986 if (*(array++) != 0) {
987 return true;
988 }
989 }
990 return false;
991 }
992
ProcessEventTimestamp(const input_event & event)993 int64_t InputHub::ProcessEventTimestamp(const input_event &event)
994 {
995 const int64_t inputEventTime = event.input_event_sec * 1000000000LL + event.input_event_usec * 1000LL;
996 return inputEventTime;
997 }
998
TestBit(uint32_t bit,const uint8_t * array)999 bool InputHub::TestBit(uint32_t bit, const uint8_t *array)
1000 {
1001 constexpr int units = 8;
1002 return (array)[(bit) / units] & (1 << ((bit) % units));
1003 }
1004
SizeofBitArray(uint32_t bit)1005 uint32_t InputHub::SizeofBitArray(uint32_t bit)
1006 {
1007 constexpr int round = 7;
1008 constexpr int divisor = 8;
1009 return ((bit) + round) / divisor;
1010 }
1011
SaveAffectDhId(bool isEnable,const std::string & dhId,AffectDhIds & affDhIds)1012 void InputHub::SaveAffectDhId(bool isEnable, const std::string &dhId, AffectDhIds &affDhIds)
1013 {
1014 if (isEnable) {
1015 affDhIds.sharingDhIds.push_back(dhId);
1016 } else {
1017 affDhIds.noSharingDhIds.push_back(dhId);
1018 }
1019 }
1020
SetSupportInputType(bool enabled,const uint32_t & inputTypes)1021 AffectDhIds InputHub::SetSupportInputType(bool enabled, const uint32_t &inputTypes)
1022 {
1023 AffectDhIds affDhIds;
1024 inputTypes_ = inputTypes;
1025 DHLOGI("SetSupportInputType: inputTypes=0x%x,", inputTypes_.load());
1026 std::unique_lock<std::mutex> deviceLock(devicesMutex_);
1027 for (const auto &[id, device] : devices_) {
1028 if (device->classes & inputTypes_) {
1029 device->isShare = enabled;
1030 DHLOGW("ByType dhid:%s, isshare:%d", GetAnonyString(device->identifier.descriptor).c_str(), enabled);
1031 SaveAffectDhId(enabled, device->identifier.descriptor, affDhIds);
1032 }
1033 }
1034
1035 return affDhIds;
1036 }
1037
SetSharingDevices(bool enabled,std::vector<std::string> dhIds)1038 AffectDhIds InputHub::SetSharingDevices(bool enabled, std::vector<std::string> dhIds)
1039 {
1040 AffectDhIds affDhIds;
1041 std::unique_lock<std::mutex> deviceLock(devicesMutex_);
1042 DHLOGI("SetSharingDevices start");
1043 for (auto dhId : dhIds) {
1044 DHLOGI("SetSharingDevices dhId: %s, size: %d, enabled: %d", GetAnonyString(dhId).c_str(), devices_.size(),
1045 enabled);
1046 sharedDHIds_[dhId] = enabled;
1047 for (const auto &[id, device] : devices_) {
1048 DHLOGI("deviceName %s ,dhId: %s ", device->identifier.name.c_str(),
1049 GetAnonyString(device->identifier.descriptor).c_str());
1050 if (device->identifier.descriptor == dhId) {
1051 device->isShare = enabled;
1052 DHLOGW("dhid:%s, isshare:%d", GetAnonyString(device->identifier.descriptor).c_str(), enabled);
1053 SaveAffectDhId(enabled, device->identifier.descriptor, affDhIds);
1054 break;
1055 }
1056 }
1057 }
1058 DHLOGI("SetSharingDevices end");
1059 return affDhIds;
1060 }
1061
GetShareMousePathByDhId(std::vector<std::string> dhIds,std::string & path,std::string & dhId)1062 void InputHub::GetShareMousePathByDhId(std::vector<std::string> dhIds, std::string &path, std::string &dhId)
1063 {
1064 DHLOGI("GetShareMousePathByDhId: devices_.size:%d,", devices_.size());
1065 std::unique_lock<std::mutex> deviceLock(devicesMutex_);
1066 for (auto dhId_ : dhIds) {
1067 for (const auto &[id, device] : devices_) {
1068 if (device == nullptr) {
1069 DHLOGE("device is nullptr");
1070 continue;
1071 }
1072 DHLOGI("descriptor:%s, isShare[%d], type[%d]", GetAnonyString(device->identifier.descriptor).c_str(),
1073 device->isShare, device->classes);
1074 if ((device->identifier.descriptor == dhId_) &&
1075 ((device->classes & INPUT_DEVICE_CLASS_CURSOR) != 0)) {
1076 dhId = dhId_;
1077 path = device->path;
1078 return; // return First shared mouse
1079 }
1080 }
1081 }
1082 }
1083
GetShareKeyboardPathsByDhIds(std::vector<std::string> dhIds,std::vector<std::string> & shareDhidsPaths,std::vector<std::string> & shareDhIds)1084 void InputHub::GetShareKeyboardPathsByDhIds(std::vector<std::string> dhIds, std::vector<std::string> &shareDhidsPaths,
1085 std::vector<std::string> &shareDhIds)
1086 {
1087 DHLOGI("GetShareKeyboardPathsByDhIds: devices_.size:%d,", devices_.size());
1088 std::unique_lock<std::mutex> deviceLock(devicesMutex_);
1089 for (auto dhId_ : dhIds) {
1090 for (const auto &[id, device] : devices_) {
1091 if (device == nullptr) {
1092 DHLOGE("device is nullptr");
1093 continue;
1094 }
1095 DHLOGI("descriptor:%s, isShare[%d], type[%d]", GetAnonyString(device->identifier.descriptor).c_str(),
1096 device->isShare, device->classes);
1097 if ((device->identifier.descriptor == dhId_) &&
1098 ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0)) {
1099 shareDhIds.push_back(dhId_);
1100 shareDhidsPaths.push_back(device->path);
1101 }
1102 }
1103 }
1104 }
1105
GetDevicesInfoByType(const uint32_t inputTypes,std::map<int32_t,std::string> & datas)1106 void InputHub::GetDevicesInfoByType(const uint32_t inputTypes, std::map<int32_t, std::string> &datas)
1107 {
1108 uint32_t dhType = 0;
1109
1110 if ((inputTypes & static_cast<uint32_t>(DInputDeviceType::MOUSE)) != 0) {
1111 dhType |= INPUT_DEVICE_CLASS_CURSOR;
1112 }
1113
1114 if ((inputTypes & static_cast<uint32_t>(DInputDeviceType::KEYBOARD)) != 0) {
1115 dhType |= INPUT_DEVICE_CLASS_KEYBOARD;
1116 }
1117
1118 if ((inputTypes & static_cast<uint32_t>(DInputDeviceType::TOUCHSCREEN)) != 0) {
1119 dhType |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
1120 }
1121
1122 std::unique_lock<std::mutex> deviceLock(devicesMutex_);
1123 for (const auto &[id, device] : devices_) {
1124 if (device->classes & dhType) {
1125 datas.insert(std::pair<int32_t, std::string>(device->fd, device->identifier.descriptor));
1126 }
1127 }
1128 }
1129
GetDevicesInfoByDhId(std::vector<std::string> dhidsVec,std::map<int32_t,std::string> & datas)1130 void InputHub::GetDevicesInfoByDhId(std::vector<std::string> dhidsVec, std::map<int32_t, std::string> &datas)
1131 {
1132 for (auto dhId : dhidsVec) {
1133 std::unique_lock<std::mutex> deviceLock(devicesMutex_);
1134 for (const auto &[id, device] : devices_) {
1135 if (device->identifier.descriptor == dhId) {
1136 datas.insert(std::pair<int32_t, std::string>(device->fd, dhId));
1137 }
1138 }
1139 }
1140 }
1141
IsAllDevicesStoped()1142 bool InputHub::IsAllDevicesStoped()
1143 {
1144 std::unique_lock<std::mutex> deviceLock(devicesMutex_);
1145 for (const auto &[dhId, isShared] : sharedDHIds_) {
1146 DHLOGI("the dhId: %s, isShared: %d", GetAnonyString(dhId).c_str(), isShared);
1147 if (isShared) {
1148 return false;
1149 }
1150 }
1151 return true;
1152 }
1153
RecordDeviceLog(const int32_t deviceId,const std::string & devicePath,const InputDevice & identifier)1154 void InputHub::RecordDeviceLog(const int32_t deviceId, const std::string &devicePath, const InputDevice &identifier)
1155 {
1156 DHLOGI("add device %d: %s\n", deviceId, devicePath.c_str());
1157 DHLOGI(" bus: %04x\n"
1158 " vendor %04x\n"
1159 " product %04x\n"
1160 " version %04x\n",
1161 identifier.bus, identifier.vendor, identifier.product, identifier.version);
1162 DHLOGI(" name: \"%s\"\n", identifier.name.c_str());
1163 DHLOGI(" physicalPath: \"%s\"\n", identifier.physicalPath.c_str());
1164 DHLOGI(" unique id: \"%s\"\n", identifier.uniqueId.c_str());
1165 DHLOGI(" descriptor: \"%s\"\n", GetAnonyString(identifier.descriptor).c_str());
1166 }
1167
RecordEventLog(const RawEvent * event)1168 void InputHub::RecordEventLog(const RawEvent *event)
1169 {
1170 std::string eventType = "";
1171 switch (event->type) {
1172 case EV_KEY:
1173 eventType = "EV_KEY";
1174 break;
1175 case EV_REL:
1176 eventType = "EV_REL";
1177 break;
1178 case EV_ABS:
1179 eventType = "EV_ABS";
1180 break;
1181 case EV_SYN:
1182 eventType = "EV_SYN";
1183 break;
1184 default:
1185 eventType = "other type " + std::to_string(event->type);
1186 break;
1187 }
1188 DHLOGD("1.E2E-Test Sink collect event, EventType: %s, Code: %d, Value: %d, Path: %s, descriptor: %s,"
1189 "When:%" PRId64 "", eventType.c_str(), event->code, event->value, event->path.c_str(),
1190 GetAnonyString(event->descriptor).c_str(), event->when);
1191 }
1192
HandleTouchScreenEvent(struct input_event readBuffer[],const size_t count,std::vector<bool> & needFilted)1193 void InputHub::HandleTouchScreenEvent(struct input_event readBuffer[], const size_t count,
1194 std::vector<bool> &needFilted)
1195 {
1196 std::vector<std::pair<size_t, size_t>> absIndexs;
1197 int32_t firstIndex = -1;
1198 int32_t lastIndex = -1;
1199
1200 for (size_t i = 0; i < count; i++) {
1201 struct input_event& iev = readBuffer[i];
1202 if ((iev.type == EV_ABS) && (iev.code == ABS_X || iev.code == ABS_MT_POSITION_X)) {
1203 firstIndex = static_cast<int32_t>(i);
1204 } else if (iev.type == EV_SYN) {
1205 lastIndex = static_cast<int32_t>(i);
1206 }
1207 if ((firstIndex >= 0) && (lastIndex > firstIndex)) {
1208 absIndexs.emplace_back(std::make_pair((size_t)firstIndex, (size_t)lastIndex));
1209 }
1210 }
1211
1212 AbsInfo absInfo = {
1213 .absX = 0,
1214 .absY = 0,
1215 .absXIndex = -1,
1216 .absYIndex = -1,
1217 };
1218 for (auto iter : absIndexs) {
1219 absInfo.absXIndex = -1;
1220 absInfo.absYIndex = -1;
1221
1222 for (size_t j = iter.first; j <= iter.second; j++) {
1223 struct input_event &iev = readBuffer[j];
1224 if (iev.code == ABS_X || iev.code == ABS_MT_POSITION_X) {
1225 absInfo.absX = static_cast<uint32_t>(iev.value);
1226 absInfo.absXIndex = static_cast<int32_t>(j);
1227 }
1228 if (iev.code == ABS_Y || iev.code == ABS_MT_POSITION_Y) {
1229 absInfo.absY = static_cast<uint32_t>(iev.value);
1230 absInfo.absYIndex = static_cast<int32_t>(j);
1231 }
1232 }
1233
1234 if ((absInfo.absXIndex < 0) || (absInfo.absYIndex < 0)) {
1235 for (size_t j = iter.first; j <= iter.second; j++) {
1236 needFilted[j] = true;
1237 }
1238 continue;
1239 }
1240 if (!CheckTouchPointRegion(readBuffer, absInfo)) {
1241 for (size_t j = iter.first; j <= iter.second; j++) {
1242 needFilted[j] = true;
1243 }
1244 }
1245 }
1246 }
1247
CheckTouchPointRegion(struct input_event readBuffer[],const AbsInfo & absInfo)1248 bool InputHub::CheckTouchPointRegion(struct input_event readBuffer[], const AbsInfo &absInfo)
1249 {
1250 auto sinkInfos = DInputContext::GetInstance().GetAllSinkScreenInfo();
1251
1252 for (const auto& [id, sinkInfo] : sinkInfos) {
1253 auto info = sinkInfo.transformInfo;
1254 if ((absInfo.absX >= info.sinkWinPhyX) && (absInfo.absX <= (info.sinkWinPhyX + info.sinkProjPhyWidth))
1255 && (absInfo.absY >= info.sinkWinPhyY) && (absInfo.absY <= (info.sinkWinPhyY + info.sinkProjPhyHeight))) {
1256 touchDescriptor = sinkInfo.srcScreenInfo.sourcePhyId;
1257 readBuffer[absInfo.absXIndex].value = (absInfo.absX - info.sinkWinPhyX) * info.coeffWidth;
1258 readBuffer[absInfo.absYIndex].value = (absInfo.absY - info.sinkWinPhyY) * info.coeffHeight;
1259 return true;
1260 }
1261 }
1262 return false;
1263 }
1264
Device(int fd,int32_t id,const std::string & path,const InputDevice & identifier)1265 InputHub::Device::Device(int fd, int32_t id, const std::string &path,
1266 const InputDevice &identifier) : next(nullptr), fd(fd), id(id), path(path), identifier(identifier),
1267 classes(0), enabled(false), isShare(false), isVirtual(fd < 0) {
1268 memset_s(keyBitmask, sizeof(keyBitmask), 0, sizeof(keyBitmask));
1269 memset_s(absBitmask, sizeof(absBitmask), 0, sizeof(absBitmask));
1270 memset_s(relBitmask, sizeof(relBitmask), 0, sizeof(relBitmask));
1271 }
1272
~Device()1273 InputHub::Device::~Device()
1274 {
1275 Close();
1276 }
1277
Close()1278 void InputHub::Device::Close()
1279 {
1280 if (fd >= 0) {
1281 ::close(fd);
1282 fd = UN_INIT_FD_VALUE;
1283 }
1284 }
1285
Enable()1286 int32_t InputHub::Device::Enable()
1287 {
1288 char canonicalPath[PATH_MAX + 1] = {0x00};
1289
1290 if (path.length() == 0 || path.length() > PATH_MAX || realpath(path.c_str(), canonicalPath) == nullptr) {
1291 DHLOGE("path check fail, error path: %s", path.c_str());
1292 return ERR_DH_INPUT_HUB_DEVICE_ENABLE_FAIL;
1293 }
1294 fd = open(canonicalPath, O_RDWR | O_CLOEXEC | O_NONBLOCK);
1295 if (fd < 0) {
1296 DHLOGE("could not open %s, %s\n", path.c_str(), ConvertErrNo().c_str());
1297 return ERR_DH_INPUT_HUB_DEVICE_ENABLE_FAIL;
1298 }
1299 enabled = true;
1300 return DH_SUCCESS;
1301 }
1302
Disable()1303 int32_t InputHub::Device::Disable()
1304 {
1305 Close();
1306 enabled = false;
1307 return DH_SUCCESS;
1308 }
1309
HasValidFd() const1310 bool InputHub::Device::HasValidFd() const
1311 {
1312 return !isVirtual && enabled;
1313 }
1314 } // namespace DistributedInput
1315 } // namespace DistributedHardware
1316 } // namespace OHOS
1317