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