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