1/* 2 * Copyright (c) 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 "libinput_wrapper.h" 17 18#include <cinttypes> 19#include <climits> 20#include <iostream> 21 22#include <dirent.h> 23#include <fcntl.h> 24#include <sys/epoll.h> 25#include <unistd.h> 26 27#include "define_multimodal.h" 28#include "util.h" 29 30#undef MMI_LOG_DOMAIN 31#define MMI_LOG_DOMAIN MMI_LOG_SERVER 32#undef MMI_LOG_TAG 33#define MMI_LOG_TAG "LibinputWrapper" 34 35namespace OHOS { 36namespace MMI { 37namespace { 38constexpr int32_t WAIT_TIME_FOR_INPUT { 10 }; 39constexpr int32_t MAX_RETRY_COUNT { 5 }; 40} // namespace 41 42LibinputWrapper::~LibinputWrapper() 43{ 44 if (input_ != nullptr) { 45 libinput_unref(input_); 46 } 47} 48 49constexpr static libinput_interface LIBINPUT_INTERFACE = { 50 .open_restricted = [](const char *path, int32_t flags, void *user_data)->int32_t { 51 if (path == nullptr) { 52 MMI_HILOGWK("Input device path is nullptr"); 53 return RET_ERR; 54 } 55 char realPath[PATH_MAX] = {}; 56 if (realpath(path, realPath) == nullptr) { 57 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME_FOR_INPUT)); 58 MMI_HILOGWK("The error path is %{private}s", path); 59 return RET_ERR; 60 } 61 int32_t fd; 62 for (int32_t i = 0; i < MAX_RETRY_COUNT; i++) { 63 fd = open(realPath, flags); 64 if (fd >= 0) { 65 break; 66 } 67 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME_FOR_INPUT)); 68 } 69 int32_t errNo = errno; 70 MMI_HILOGWK("Libinput .open_restricted path:%{private}s,fd:%{public}d,errno:%{public}d", path, fd, errNo); 71 return fd < 0 ? RET_ERR : fd; 72 }, 73 .close_restricted = [](int32_t fd, void *user_data) 74 { 75 if (fd < 0) { 76 return; 77 } 78 MMI_HILOGI("Libinput .close_restricted fd:%{public}d", fd); 79 close(fd); 80 }, 81}; 82 83bool LibinputWrapper::Init() 84{ 85 input_ = libinput_path_create_context(&LIBINPUT_INTERFACE, nullptr); 86 CHKPF(input_); 87 fd_ = libinput_get_fd(input_); 88 if (fd_ < 0) { 89 libinput_unref(input_); 90 fd_ = -1; 91 return false; 92 } 93 return true; 94} 95 96struct libinput_event* LibinputWrapper::Dispatch() 97{ 98 CHKPP(input_); 99 if (libinput_dispatch(input_) != 0) { 100 std::cout << "Failed to dispatch input event" << std::endl; 101 return nullptr; 102 } 103 return libinput_get_event(input_); 104} 105 106void LibinputWrapper::DrainEvents() 107{ 108 CHKPV(input_); 109 struct libinput_event *event; 110 111 libinput_dispatch(input_); 112 while ((event = libinput_get_event(input_))) { 113 libinput_event_destroy(event); 114 libinput_dispatch(input_); 115 } 116} 117 118bool LibinputWrapper::AddPath(const std::string &path) 119{ 120 CHKPF(input_); 121 auto pos = devices_.find(path); 122 if (pos != devices_.end()) { 123 return true; 124 } 125 libinput_device* device = libinput_path_add_device(input_, path.c_str()); 126 CHKPF(device); 127 devices_[std::move(path)] = libinput_device_ref(device); 128 return true; 129} 130 131void LibinputWrapper::RemovePath(const std::string &path) 132{ 133 CHKPV(input_); 134 auto pos = devices_.find(path); 135 if (pos != devices_.end()) { 136 libinput_path_remove_device(pos->second); 137 libinput_device_unref(pos->second); 138 devices_.erase(pos); 139 } 140} 141} // namespace MMI 142} // namespace OHOS 143