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 39namespace OHOS { 40namespace Msdp { 41namespace DeviceStatus { 42struct Range { 43 size_t start = 0; 44 size_t end = 0; 45}; 46 47namespace { 48const struct Range KEY_BLOCKS[] { { KEY_ESC, BTN_MISC }, 49 { KEY_OK, BTN_DPAD_UP }, 50 { KEY_ALS_TOGGLE, BTN_TRIGGER_HAPPY } }; 51} // namespace 52 53VInputDevice::VInputDevice(const std::string &node) : devPath_(node) {} 54 55VInputDevice::~VInputDevice() 56{ 57 Close(); 58} 59 60int32_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 93void 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 104bool 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 115int32_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 142void 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 182void 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 191void 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 199void 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 227void VInputDevice::UpdateCapability() 228{ 229 CALL_DEBUG_ENTER; 230 CheckPointers(); 231 CheckKeys(); 232} 233 234bool 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 244bool 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 257void 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 276bool VInputDevice::HasAbsCoord() const 277{ 278 return HasAbs(ABS_X) && HasAbs(ABS_Y); 279} 280 281bool VInputDevice::HasMtCoord() const 282{ 283 return HasAbs(ABS_MT_POSITION_X) && HasAbs(ABS_MT_POSITION_Y); 284} 285 286bool VInputDevice::HasRelCoord() const 287{ 288 return HasRel(REL_X) && HasRel(REL_Y); 289} 290 291void 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 306void 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 317void 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 327void 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 342void 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