1 /*
2 * Copyright (c) 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 "v_input_device.h"
17
18 #include <fcntl.h>
19 #include <securec.h>
20 #include <sys/ioctl.h>
21 #include <unistd.h>
22
23 #include <cstring>
24 #include <fstream>
25 #include <map>
26 #include <regex>
27 #include <sstream>
28
29 #include "devicestatus_define.h"
30 #include "devicestatus_errors.h"
31 #include "fi_log.h"
32 #include "napi_constants.h"
33 #include "utility.h"
34 #include "virtual_device_defines.h"
35
36 #undef LOG_TAG
37 #define LOG_TAG "VInputDevice"
38
39 namespace OHOS {
40 namespace Msdp {
41 namespace DeviceStatus {
42 struct Range {
43 size_t start = 0;
44 size_t end = 0;
45 };
46
47 namespace {
48 const struct Range KEY_BLOCKS[] { { KEY_ESC, BTN_MISC },
49 { KEY_OK, BTN_DPAD_UP },
50 { KEY_ALS_TOGGLE, BTN_TRIGGER_HAPPY } };
51 } // namespace
52
VInputDevice(const std::string & node)53 VInputDevice::VInputDevice(const std::string &node) : devPath_(node) {}
54
~VInputDevice()55 VInputDevice::~VInputDevice()
56 {
57 Close();
58 }
59
Open()60 int32_t VInputDevice::Open()
61 {
62 CALL_DEBUG_ENTER;
63 char buf[PATH_MAX] {};
64 if (realpath(devPath_.c_str(), buf) == nullptr) {
65 FI_HILOGE("Not real path:%{private}s", devPath_.c_str());
66 return RET_ERR;
67 }
68
69 int32_t nRetries = 6;
70 for (;;) {
71 Utility::ShowUserAndGroup();
72 Utility::ShowFileAttributes(buf);
73 fd_ = open(buf, O_RDWR | O_NONBLOCK | O_CLOEXEC);
74 if (fd_ < 0) {
75 FI_HILOGE("Unable to open device \'%{public}s\':%{public}s", buf, strerror(errno));
76 if (nRetries-- > 0) {
77 std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME));
78 FI_HILOGI("Retry opening device \'%{public}s\'", buf);
79 } else {
80 return RET_ERR;
81 }
82 } else {
83 FI_HILOGD("Opening \'%{public}s\' successfully", buf);
84 break;
85 }
86 }
87 QueryDeviceInfo();
88 QuerySupportedEvents();
89 UpdateCapability();
90 return RET_OK;
91 }
92
Close()93 void VInputDevice::Close()
94 {
95 CALL_DEBUG_ENTER;
96 if (fd_ >= 0) {
97 if (close(fd_) != 0) {
98 FI_HILOGE("Close error:%{public}s", strerror(errno));
99 }
100 fd_ = -1;
101 }
102 }
103
QueryAbsInfo(size_t abs,struct input_absinfo & absInfo)104 bool VInputDevice::QueryAbsInfo(size_t abs, struct input_absinfo &absInfo)
105 {
106 CALL_DEBUG_ENTER;
107 errno_t ret = memset_s(&absInfo, sizeof(absInfo), 0, sizeof(absInfo));
108 if (ret != EOK) {
109 FI_HILOGE("Call memset_s failed");
110 return false;
111 }
112 return (ioctl(fd_, EVIOCGABS(abs), &absInfo) >= 0);
113 }
114
SendEvent(uint16_t type,uint16_t code,int32_t value)115 int32_t VInputDevice::SendEvent(uint16_t type, uint16_t code, int32_t value)
116 {
117 CALL_DEBUG_ENTER;
118 if (!IsActive()) {
119 FI_HILOGE("No active device");
120 return RET_ERR;
121 }
122 struct input_event event {
123 .type = type,
124 .code = code,
125 .value = value
126 };
127 struct timeval tv;
128 if (gettimeofday(&tv, nullptr) != 0) {
129 FI_HILOGE("Failed to get current time");
130 return RET_ERR;
131 }
132 event.input_event_sec = tv.tv_sec;
133 event.input_event_usec = tv.tv_usec;
134 ssize_t ret = ::write(fd_, &event, sizeof(struct input_event));
135 if (ret < 0) {
136 FI_HILOGE("Failed to send event:%{public}s", strerror(errno));
137 return RET_ERR;
138 }
139 return RET_OK;
140 }
141
QueryDeviceInfo()142 void VInputDevice::QueryDeviceInfo()
143 {
144 CALL_DEBUG_ENTER;
145 char buffer[PATH_MAX] { 0 };
146
147 int32_t rc = ioctl(fd_, EVIOCGNAME(sizeof(buffer) - 1), &buffer);
148 if (rc < 0) {
149 FI_HILOGE("Could not get device name:%{public}s", strerror(errno));
150 } else {
151 name_.assign(buffer);
152 }
153
154 rc = ioctl(fd_, EVIOCGID, &inputId_);
155 if (rc < 0) {
156 FI_HILOGE("Couldn't not get device input id:%{public}s", strerror(errno));
157 }
158 errno_t ret = memset_s(buffer, sizeof(buffer), 0, sizeof(buffer));
159 if (ret != EOK) {
160 FI_HILOGE("Call memset_s was a failure");
161 return;
162 }
163 rc = ioctl(fd_, EVIOCGPHYS(sizeof(buffer) - 1), &buffer);
164 if (rc < 0) {
165 FI_HILOGE("Couldn't get location:%{public}s", strerror(errno));
166 } else {
167 phys_.assign(buffer);
168 }
169 ret = memset_s(buffer, sizeof(buffer), 0, sizeof(buffer));
170 if (ret != EOK) {
171 FI_HILOGE("Call memset_s was a failure");
172 return;
173 }
174 rc = ioctl(fd_, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer);
175 if (rc < 0) {
176 FI_HILOGE("Could not get uniq:%{public}s", strerror(errno));
177 } else {
178 uniq_.assign(buffer);
179 }
180 }
181
GetEventMask(const std::string & eventName,uint32_t type,std::size_t arrayLength,uint8_t * whichBitMask) const182 void VInputDevice::GetEventMask(const std::string &eventName, uint32_t type,
183 std::size_t arrayLength, uint8_t *whichBitMask) const
184 {
185 int32_t rc = ioctl(fd_, EVIOCGBIT(type, arrayLength), whichBitMask);
186 if (rc < 0) {
187 FI_HILOGE("Could not get events %{public}s mask:%{public}s", eventName.c_str(), strerror(errno));
188 }
189 }
190
GetPropMask(const std::string & eventName,std::size_t arrayLength,uint8_t * whichBitMask) const191 void VInputDevice::GetPropMask(const std::string &eventName, std::size_t arrayLength, uint8_t *whichBitMask) const
192 {
193 int32_t rc = ioctl(fd_, EVIOCGPROP(arrayLength), whichBitMask);
194 if (rc < 0) {
195 FI_HILOGE("Could not get %{public}s mask:%{public}s", eventName.c_str(), strerror(errno));
196 }
197 }
198
QuerySupportedEvents()199 void VInputDevice::QuerySupportedEvents()
200 {
201 CALL_DEBUG_ENTER;
202 // get events mask
203 GetEventMask("", 0, sizeof(evBitmask_), evBitmask_);
204
205 // get key events
206 GetEventMask("key", EV_KEY, sizeof(keyBitmask_), keyBitmask_);
207
208 // get abs events
209 GetEventMask("abs", EV_ABS, sizeof(absBitmask_), absBitmask_);
210
211 // get rel events
212 GetEventMask("rel", EV_REL, sizeof(relBitmask_), relBitmask_);
213
214 // get msc events
215 GetEventMask("msc", EV_MSC, sizeof(mscBitmask_), mscBitmask_);
216
217 // get led events
218 GetEventMask("led", EV_LED, sizeof(ledBitmask_), ledBitmask_);
219
220 // get rep events
221 GetEventMask("rep", EV_REP, sizeof(repBitmask_), repBitmask_);
222
223 // get properties mask
224 GetPropMask("properties", sizeof(propBitmask_), propBitmask_);
225 }
226
UpdateCapability()227 void VInputDevice::UpdateCapability()
228 {
229 CALL_DEBUG_ENTER;
230 CheckPointers();
231 CheckKeys();
232 }
233
HasAxesOrButton(size_t start,size_t end,const uint8_t * whichBitMask) const234 bool VInputDevice::HasAxesOrButton(size_t start, size_t end, const uint8_t* whichBitMask) const
235 {
236 for (size_t type = start; type < end; ++type) {
237 if (TestBit(type, whichBitMask)) {
238 return true;
239 }
240 }
241 return false;
242 }
243
HasJoystickAxesOrButtons() const244 bool VInputDevice::HasJoystickAxesOrButtons() const
245 {
246 if (!TestBit(BTN_JOYSTICK - 1, keyBitmask_)) {
247 if (HasAxesOrButton(BTN_JOYSTICK, BTN_DIGI, keyBitmask_) ||
248 // BTN_TRIGGER_HAPPY40 + 1 : Iteration limit
249 HasAxesOrButton(BTN_TRIGGER_HAPPY1, BTN_TRIGGER_HAPPY40 + 1, keyBitmask_) ||
250 HasAxesOrButton(BTN_DPAD_UP, BTN_DPAD_RIGHT + 1, keyBitmask_)) { // BTN_DPAD_RIGHT + 1 : Iteration limit
251 return true;
252 }
253 }
254 return HasAxesOrButton(ABS_RX, ABS_PRESSURE, absBitmask_);
255 }
256
PrintCapsDevice() const257 void VInputDevice::PrintCapsDevice() const
258 {
259 std::map<std::size_t, std::string> deviceComparisonTable {
260 { DEVICE_CAP_KEYBOARD, "keyboard" },
261 { DEVICE_CAP_TOUCH, "touch device" },
262 { DEVICE_CAP_TABLET_TOOL, "tablet tool" },
263 { DEVICE_CAP_POINTER, "pointer" },
264 { DEVICE_CAP_TABLET_PAD, "pad" },
265 { DEVICE_CAP_GESTURE, "gesture" },
266 { DEVICE_CAP_SWITCH, "switch" },
267 { DEVICE_CAP_JOYSTICK, "joystick" }
268 };
269 for (const auto& [cap, name] : deviceComparisonTable) {
270 if (caps_.test(cap)) {
271 FI_HILOGD("This is %{public}s", name.c_str());
272 }
273 }
274 }
275
HasAbsCoord() const276 bool VInputDevice::HasAbsCoord() const
277 {
278 return HasAbs(ABS_X) && HasAbs(ABS_Y);
279 }
280
HasMtCoord() const281 bool VInputDevice::HasMtCoord() const
282 {
283 return HasAbs(ABS_MT_POSITION_X) && HasAbs(ABS_MT_POSITION_Y);
284 }
285
HasRelCoord() const286 bool VInputDevice::HasRelCoord() const
287 {
288 return HasRel(REL_X) && HasRel(REL_Y);
289 }
290
CheckAbs()291 void VInputDevice::CheckAbs()
292 {
293 if (HasKey(BTN_STYLUS) || HasKey(BTN_TOOL_PEN)) {
294 caps_.set(DEVICE_CAP_TABLET_TOOL);
295 } else if (HasKey(BTN_TOOL_FINGER) && !HasKey(BTN_TOOL_PEN) && !HasProperty(INPUT_PROP_DIRECT)) {
296 caps_.set(DEVICE_CAP_POINTER);
297 } else if (HasAxesOrButton(BTN_MOUSE, BTN_JOYSTICK, keyBitmask_)) {
298 caps_.set(DEVICE_CAP_POINTER);
299 } else if (HasKey(BTN_TOUCH) || HasProperty(INPUT_PROP_DIRECT)) {
300 caps_.set(DEVICE_CAP_TOUCH);
301 } else if (HasJoystickAxesOrButtons()) {
302 caps_.set(DEVICE_CAP_JOYSTICK);
303 }
304 }
305
CheckMt()306 void VInputDevice::CheckMt()
307 {
308 if (HasKey(BTN_STYLUS) || HasKey(BTN_TOOL_PEN)) {
309 caps_.set(DEVICE_CAP_TABLET_TOOL);
310 } else if (HasKey(BTN_TOOL_FINGER) && !HasKey(BTN_TOOL_PEN) && !HasProperty(INPUT_PROP_DIRECT)) {
311 caps_.set(DEVICE_CAP_POINTER);
312 } else if (HasKey(BTN_TOUCH) || HasProperty(INPUT_PROP_DIRECT)) {
313 caps_.set(DEVICE_CAP_TOUCH);
314 }
315 }
316
CheckAdditional()317 void VInputDevice::CheckAdditional()
318 {
319 if (!HasCapability(DEVICE_CAP_TABLET_TOOL) &&
320 !HasCapability(DEVICE_CAP_POINTER) &&
321 !HasCapability(DEVICE_CAP_JOYSTICK) &&
322 HasAxesOrButton(BTN_MOUSE, BTN_JOYSTICK, keyBitmask_) && (HasRelCoord() || !HasAbsCoord())) {
323 caps_.set(DEVICE_CAP_POINTER);
324 }
325 }
326
CheckPointers()327 void VInputDevice::CheckPointers()
328 {
329 CALL_DEBUG_ENTER;
330 if (HasAbsCoord()) {
331 CheckAbs();
332 } else if (HasJoystickAxesOrButtons()) {
333 caps_.set(DEVICE_CAP_JOYSTICK);
334 }
335 if (HasMtCoord()) {
336 CheckMt();
337 }
338 CheckAdditional();
339 PrintCapsDevice();
340 }
341
CheckKeys()342 void VInputDevice::CheckKeys()
343 {
344 CALL_DEBUG_ENTER;
345 if (!TestBit(EV_KEY, evBitmask_)) {
346 FI_HILOGD("No EV_KEY capability");
347 return;
348 }
349 for (size_t block = 0U; block < (sizeof(KEY_BLOCKS) / sizeof(struct Range)); ++block) {
350 for (size_t key = KEY_BLOCKS[block].start; key < KEY_BLOCKS[block].end; ++key) {
351 if (TestBit(key, keyBitmask_)) {
352 FI_HILOGD("Found key %{public}zx", key);
353 caps_.set(DEVICE_CAP_KEYBOARD);
354 return;
355 }
356 }
357 }
358 }
359 } // namespace DeviceStatus
360 } // namespace Msdp
361 } // namespace