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
35 namespace OHOS {
36 namespace MMI {
37 namespace {
38 constexpr int32_t WAIT_TIME_FOR_INPUT { 10 };
39 constexpr int32_t MAX_RETRY_COUNT { 5 };
40 } // namespace
41
~LibinputWrapper()42 LibinputWrapper::~LibinputWrapper()
43 {
44 if (input_ != nullptr) {
45 libinput_unref(input_);
46 }
47 }
48
49 constexpr static libinput_interface LIBINPUT_INTERFACE = {
__anon89a9fab50202()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)
__anon89a9fab50302() 74 {
75 if (fd < 0) {
76 return;
77 }
78 MMI_HILOGI("Libinput .close_restricted fd:%{public}d", fd);
79 close(fd);
80 },
81 };
82
Init()83 bool 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
Dispatch()96 struct 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
DrainEvents()106 void 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
AddPath(const std::string & path)118 bool 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
RemovePath(const std::string & path)131 void 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