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