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