1f857971dSopenharmony_ci/* 2f857971dSopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 3f857971dSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4f857971dSopenharmony_ci * you may not use this file except in compliance with the License. 5f857971dSopenharmony_ci * You may obtain a copy of the License at 6f857971dSopenharmony_ci * 7f857971dSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8f857971dSopenharmony_ci * 9f857971dSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10f857971dSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11f857971dSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12f857971dSopenharmony_ci * See the License for the specific language governing permissions and 13f857971dSopenharmony_ci * limitations under the License. 14f857971dSopenharmony_ci */ 15f857971dSopenharmony_ci 16f857971dSopenharmony_ci#include "virtual_device_builder.h" 17f857971dSopenharmony_ci 18f857971dSopenharmony_ci#include <cerrno> 19f857971dSopenharmony_ci#include <csignal> 20f857971dSopenharmony_ci#include <cstring> 21f857971dSopenharmony_ci#include <fstream> 22f857971dSopenharmony_ci#include <iostream> 23f857971dSopenharmony_ci#include <regex> 24f857971dSopenharmony_ci#include <sstream> 25f857971dSopenharmony_ci#include <map> 26f857971dSopenharmony_ci 27f857971dSopenharmony_ci#include <dirent.h> 28f857971dSopenharmony_ci#include <fcntl.h> 29f857971dSopenharmony_ci#include <unistd.h> 30f857971dSopenharmony_ci#include <sys/ioctl.h> 31f857971dSopenharmony_ci#include <sys/stat.h> 32f857971dSopenharmony_ci#include <sys/types.h> 33f857971dSopenharmony_ci 34f857971dSopenharmony_ci#include <securec.h> 35f857971dSopenharmony_ci 36f857971dSopenharmony_ci#include "devicestatus_define.h" 37f857971dSopenharmony_ci#include "fi_log.h" 38f857971dSopenharmony_ci#include "if_stream_wrap.h" 39f857971dSopenharmony_ci#include "napi_constants.h" 40f857971dSopenharmony_ci#include "utility.h" 41f857971dSopenharmony_ci#include "virtual_mouse.h" 42f857971dSopenharmony_ci#include "virtual_touchscreen.h" 43f857971dSopenharmony_ci 44f857971dSopenharmony_ci#undef LOG_TAG 45f857971dSopenharmony_ci#define LOG_TAG "VirtualDeviceBuilder" 46f857971dSopenharmony_ci 47f857971dSopenharmony_cinamespace OHOS { 48f857971dSopenharmony_cinamespace Msdp { 49f857971dSopenharmony_cinamespace DeviceStatus { 50f857971dSopenharmony_cinamespace { 51f857971dSopenharmony_ciconstexpr int32_t MAXIMUM_WAIT_TIME_ALLOWED { 3000 }; 52f857971dSopenharmony_ciconstexpr int32_t MINIMUM_WAIT_TIME_ALLOWED { 5 }; 53f857971dSopenharmony_ciconstexpr ssize_t MAXIMUM_FILESIZE_ALLOWED { 0x100000 }; 54f857971dSopenharmony_ci} // namespace 55f857971dSopenharmony_ci 56f857971dSopenharmony_ciVirtualDeviceBuilder::VirtualDeviceBuilder(const std::string &name, uint16_t bustype, 57f857971dSopenharmony_ci uint16_t vendor, uint16_t product) 58f857971dSopenharmony_ci : uinputDev_ { 59f857971dSopenharmony_ci .id = { 60f857971dSopenharmony_ci .bustype = bustype, 61f857971dSopenharmony_ci .vendor = vendor, 62f857971dSopenharmony_ci .product = product, 63f857971dSopenharmony_ci .version = 1 64f857971dSopenharmony_ci } 65f857971dSopenharmony_ci } 66f857971dSopenharmony_ci{ 67f857971dSopenharmony_ci if (strcpy_s(uinputDev_.name, sizeof(uinputDev_.name), name.c_str()) != EOK) { 68f857971dSopenharmony_ci FI_HILOGE("Invalid device name:\'%{public}s\'", name.c_str()); 69f857971dSopenharmony_ci } 70f857971dSopenharmony_ci} 71f857971dSopenharmony_ci 72f857971dSopenharmony_ciVirtualDeviceBuilder::VirtualDeviceBuilder(const std::string &name, std::shared_ptr<VirtualDevice> vDev) : vDev_(vDev) 73f857971dSopenharmony_ci{ 74f857971dSopenharmony_ci CopyProperties(name, vDev); 75f857971dSopenharmony_ci} 76f857971dSopenharmony_ci 77f857971dSopenharmony_ciVirtualDeviceBuilder::~VirtualDeviceBuilder() 78f857971dSopenharmony_ci{ 79f857971dSopenharmony_ci Close(); 80f857971dSopenharmony_ci} 81f857971dSopenharmony_ci 82f857971dSopenharmony_civoid VirtualDeviceBuilder::Daemonize() 83f857971dSopenharmony_ci{ 84f857971dSopenharmony_ci int32_t fd = fork(); 85f857971dSopenharmony_ci if (fd < 0) { 86f857971dSopenharmony_ci exit(EXIT_FAILURE); 87f857971dSopenharmony_ci } else if (fd > 0) { 88f857971dSopenharmony_ci exit(EXIT_SUCCESS); 89f857971dSopenharmony_ci } 90f857971dSopenharmony_ci if (setsid() < 0) { 91f857971dSopenharmony_ci exit(EXIT_SUCCESS); 92f857971dSopenharmony_ci } 93f857971dSopenharmony_ci fd = fork(); 94f857971dSopenharmony_ci if (fd < 0) { 95f857971dSopenharmony_ci exit(EXIT_FAILURE); 96f857971dSopenharmony_ci } else if (fd > 0) { 97f857971dSopenharmony_ci exit(EXIT_SUCCESS); 98f857971dSopenharmony_ci } 99f857971dSopenharmony_ci close(STDIN_FILENO); 100f857971dSopenharmony_ci fd = open("/dev/null", O_RDWR); 101f857971dSopenharmony_ci if (fd != STDIN_FILENO) { 102f857971dSopenharmony_ci exit(EXIT_FAILURE); 103f857971dSopenharmony_ci } 104f857971dSopenharmony_ci if (dup2(STDIN_FILENO, STDOUT_FILENO) != STDOUT_FILENO) { 105f857971dSopenharmony_ci exit(EXIT_FAILURE); 106f857971dSopenharmony_ci } 107f857971dSopenharmony_ci if (dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO) { 108f857971dSopenharmony_ci exit(EXIT_FAILURE); 109f857971dSopenharmony_ci } 110f857971dSopenharmony_ci} 111f857971dSopenharmony_ci 112f857971dSopenharmony_civoid VirtualDeviceBuilder::ConcatenationName(std::string &sLine) 113f857971dSopenharmony_ci{ 114f857971dSopenharmony_ci auto s = sLine.begin(); 115f857971dSopenharmony_ci while (s != sLine.end() && (isspace(*s) || (*s == '\0'))) { 116f857971dSopenharmony_ci s = sLine.erase(s); 117f857971dSopenharmony_ci } 118f857971dSopenharmony_ci while (s != sLine.end()) { 119f857971dSopenharmony_ci while (s != sLine.end() && !isspace(*s) && *s != '\0') { 120f857971dSopenharmony_ci ++s; 121f857971dSopenharmony_ci } 122f857971dSopenharmony_ci auto t = s; 123f857971dSopenharmony_ci while (t != sLine.end() && (isspace(*t) || (*t == '\0'))) { 124f857971dSopenharmony_ci ++t; 125f857971dSopenharmony_ci } 126f857971dSopenharmony_ci if (t != sLine.end()) { 127f857971dSopenharmony_ci *s++ = '_'; 128f857971dSopenharmony_ci } 129f857971dSopenharmony_ci while (s != sLine.end() && (isspace(*s) || (*s == '\0'))) { 130f857971dSopenharmony_ci s = sLine.erase(s); 131f857971dSopenharmony_ci } 132f857971dSopenharmony_ci } 133f857971dSopenharmony_ci} 134f857971dSopenharmony_ci 135f857971dSopenharmony_cibool VirtualDeviceBuilder::ExecuteUnmount(const char *id, const char *name, const std::string &direntName) 136f857971dSopenharmony_ci{ 137f857971dSopenharmony_ci std::ostringstream sPattern; 138f857971dSopenharmony_ci sPattern << "^vdevadm_(mount|clone)_-t_?" << id; 139f857971dSopenharmony_ci std::regex pattern { sPattern.str() }; 140f857971dSopenharmony_ci if (!Utility::IsInteger(direntName)) { 141f857971dSopenharmony_ci return false; 142f857971dSopenharmony_ci } 143f857971dSopenharmony_ci 144f857971dSopenharmony_ci std::ostringstream spath; 145f857971dSopenharmony_ci spath << "/proc/" << direntName; 146f857971dSopenharmony_ci struct stat statBuf; 147f857971dSopenharmony_ci if (stat(spath.str().c_str(), &statBuf) != 0) { 148f857971dSopenharmony_ci std::cout << "stat \'" << spath.str() << "\' failed: " << strerror(errno) << std::endl; 149f857971dSopenharmony_ci return false; 150f857971dSopenharmony_ci } 151f857971dSopenharmony_ci if (!S_ISDIR(statBuf.st_mode)) { 152f857971dSopenharmony_ci return false; 153f857971dSopenharmony_ci } 154f857971dSopenharmony_ci spath << "/cmdline"; 155f857971dSopenharmony_ci char realPath[PATH_MAX] = { 0 }; 156f857971dSopenharmony_ci if (realpath(spath.str().c_str(), realPath) == nullptr) { 157f857971dSopenharmony_ci std::cout << "Invalid path" << spath.str().c_str() << std::endl; 158f857971dSopenharmony_ci return false; 159f857971dSopenharmony_ci } 160f857971dSopenharmony_ci IfStreamWrap fileStream; 161f857971dSopenharmony_ci fileStream.ifStream = std::ifstream(spath.str(), std::ios::in); 162f857971dSopenharmony_ci if (!fileStream.IsOpen()) { 163f857971dSopenharmony_ci return false; 164f857971dSopenharmony_ci } 165f857971dSopenharmony_ci std::string sLine; 166f857971dSopenharmony_ci while (std::getline(fileStream.ifStream, sLine)) { 167f857971dSopenharmony_ci ConcatenationName(sLine); 168f857971dSopenharmony_ci if (std::regex_search(sLine, pattern)) { 169f857971dSopenharmony_ci std::cout << "\tfound: \'" << direntName << "\'" << std::endl; 170f857971dSopenharmony_ci int32_t pid = std::atoi(direntName.c_str()); 171f857971dSopenharmony_ci if (kill(static_cast<pid_t>(pid), SIGTERM) != 0) { 172f857971dSopenharmony_ci std::cout << "Failed to stop backing process [" << pid << "]: " << strerror(errno) << std::endl; 173f857971dSopenharmony_ci } else { 174f857971dSopenharmony_ci std::cout << "Unmount virtual " << name << " successfully." << std::endl; 175f857971dSopenharmony_ci } 176f857971dSopenharmony_ci return true; 177f857971dSopenharmony_ci } 178f857971dSopenharmony_ci } 179f857971dSopenharmony_ci return false; 180f857971dSopenharmony_ci} 181f857971dSopenharmony_ci 182f857971dSopenharmony_civoid VirtualDeviceBuilder::Unmount(const char *name, const char *id) 183f857971dSopenharmony_ci{ 184f857971dSopenharmony_ci std::cout << "Start to unmount virtual " << name << " ..." << std::endl; 185f857971dSopenharmony_ci DIR *procDir = opendir("/proc"); 186f857971dSopenharmony_ci if (procDir == nullptr) { 187f857971dSopenharmony_ci std::cout << "Failed to unmount virtual " << name << ": " << strerror(errno) << std::endl; 188f857971dSopenharmony_ci return; 189f857971dSopenharmony_ci } 190f857971dSopenharmony_ci 191f857971dSopenharmony_ci struct dirent *dent; 192f857971dSopenharmony_ci while ((dent = readdir(procDir)) != nullptr) { 193f857971dSopenharmony_ci std::string direntName { dent->d_name }; 194f857971dSopenharmony_ci if (ExecuteUnmount(id, name, direntName)) { 195f857971dSopenharmony_ci goto EXIT; 196f857971dSopenharmony_ci } 197f857971dSopenharmony_ci } 198f857971dSopenharmony_ci std::cout << "The backing process for virtual " << name << "can't be found." << std::endl; 199f857971dSopenharmony_ciEXIT: 200f857971dSopenharmony_ci if (closedir(procDir) != 0) { 201f857971dSopenharmony_ci FI_HILOGE("closedir error:%{public}s", strerror(errno)); 202f857971dSopenharmony_ci } 203f857971dSopenharmony_ci} 204f857971dSopenharmony_ci 205f857971dSopenharmony_civoid VirtualDeviceBuilder::SetSupportedEvents() 206f857971dSopenharmony_ci{ 207f857971dSopenharmony_ci static const std::map<int32_t, std::function<std::vector<uint32_t>()>> uinputTypes { 208f857971dSopenharmony_ci { UI_SET_EVBIT, [this] { return this->GetEventTypes(); } }, 209f857971dSopenharmony_ci { UI_SET_KEYBIT, [this] { return this->GetKeys(); } }, 210f857971dSopenharmony_ci { UI_SET_PROPBIT, [this] { return this->GetProperties(); } }, 211f857971dSopenharmony_ci { UI_SET_ABSBIT, [this] { return this->GetAbs(); } }, 212f857971dSopenharmony_ci { UI_SET_RELBIT, [this] { return this->GetRelBits(); } }, 213f857971dSopenharmony_ci { UI_SET_MSCBIT, [this] { return this->GetMiscellaneous(); } }, 214f857971dSopenharmony_ci { UI_SET_LEDBIT, [this] { return this->GetLeds(); } }, 215f857971dSopenharmony_ci { UI_SET_SWBIT, [this] { return this->GetSwitches(); } }, 216f857971dSopenharmony_ci { UI_SET_FFBIT, [this] { return this->GetRepeats(); } } 217f857971dSopenharmony_ci }; 218f857971dSopenharmony_ci 219f857971dSopenharmony_ci for (const auto &setEvents : uinputTypes) { 220f857971dSopenharmony_ci const auto &events = setEvents.second(); 221f857971dSopenharmony_ci for (const auto &e : events) { 222f857971dSopenharmony_ci if (ioctl(fd_, setEvents.first, e) < 0) { 223f857971dSopenharmony_ci FI_HILOGE("Failed while setting event type:%{public}s", strerror(errno)); 224f857971dSopenharmony_ci } 225f857971dSopenharmony_ci } 226f857971dSopenharmony_ci } 227f857971dSopenharmony_ci} 228f857971dSopenharmony_ci 229f857971dSopenharmony_civoid VirtualDeviceBuilder::SetAbsResolution() 230f857971dSopenharmony_ci{ 231f857971dSopenharmony_ci for (const auto &item : absInit_) { 232f857971dSopenharmony_ci if (ioctl(fd_, UI_ABS_SETUP, &item) < 0) { 233f857971dSopenharmony_ci FI_HILOGE("Failed while setting abs info:%{public}s", strerror(errno)); 234f857971dSopenharmony_ci } 235f857971dSopenharmony_ci } 236f857971dSopenharmony_ci} 237f857971dSopenharmony_ci 238f857971dSopenharmony_civoid VirtualDeviceBuilder::SetPhys() 239f857971dSopenharmony_ci{ 240f857971dSopenharmony_ci std::string phys; 241f857971dSopenharmony_ci 242f857971dSopenharmony_ci if (vDev_ != nullptr) { 243f857971dSopenharmony_ci phys = vDev_->GetPhys(); 244f857971dSopenharmony_ci } else { 245f857971dSopenharmony_ci static const std::map<std::string, std::string> mapNames { 246f857971dSopenharmony_ci { "Virtual Mouse", "mouse" }, 247f857971dSopenharmony_ci { "Virtual TouchScreen", "touchscreen" }, 248f857971dSopenharmony_ci { "Virtual Keyboard", "Keyboard" }, 249f857971dSopenharmony_ci }; 250f857971dSopenharmony_ci auto tIter = mapNames.find(std::string(uinputDev_.name)); 251f857971dSopenharmony_ci if (tIter == mapNames.cend()) { 252f857971dSopenharmony_ci FI_HILOGE("Unrecognized device name"); 253f857971dSopenharmony_ci return; 254f857971dSopenharmony_ci } 255f857971dSopenharmony_ci phys = tIter->second; 256f857971dSopenharmony_ci phys.append("/").append(std::to_string(getpid())); 257f857971dSopenharmony_ci } 258f857971dSopenharmony_ci 259f857971dSopenharmony_ci if (ioctl(fd_, UI_SET_PHYS, phys.c_str()) < 0) { 260f857971dSopenharmony_ci FI_HILOGE("Failed while setting phys:%{public}s", strerror(errno)); 261f857971dSopenharmony_ci } 262f857971dSopenharmony_ci} 263f857971dSopenharmony_ci 264f857971dSopenharmony_civoid VirtualDeviceBuilder::SetIdentity() 265f857971dSopenharmony_ci{ 266f857971dSopenharmony_ci if (write(fd_, &uinputDev_, sizeof(uinputDev_)) < 0) { 267f857971dSopenharmony_ci FI_HILOGE("Unable to set uinput device info:%{public}s", strerror(errno)); 268f857971dSopenharmony_ci } 269f857971dSopenharmony_ci} 270f857971dSopenharmony_ci 271f857971dSopenharmony_cibool VirtualDeviceBuilder::SetUp() 272f857971dSopenharmony_ci{ 273f857971dSopenharmony_ci CALL_DEBUG_ENTER; 274f857971dSopenharmony_ci fd_ = open("/dev/uinput", O_WRONLY | O_NONBLOCK); 275f857971dSopenharmony_ci if (fd_ < 0) { 276f857971dSopenharmony_ci FI_HILOGE("Unable to open uinput"); 277f857971dSopenharmony_ci return false; 278f857971dSopenharmony_ci } 279f857971dSopenharmony_ci 280f857971dSopenharmony_ci SetAbsResolution(); 281f857971dSopenharmony_ci SetPhys(); 282f857971dSopenharmony_ci SetSupportedEvents(); 283f857971dSopenharmony_ci SetIdentity(); 284f857971dSopenharmony_ci 285f857971dSopenharmony_ci if (ioctl(fd_, UI_DEV_CREATE) < 0) { 286f857971dSopenharmony_ci FI_HILOGE("Failed to setup uinput device"); 287f857971dSopenharmony_ci if (close(fd_) != 0) { 288f857971dSopenharmony_ci FI_HILOGE("Close error:%{public}s", strerror(errno)); 289f857971dSopenharmony_ci } 290f857971dSopenharmony_ci fd_ = -1; 291f857971dSopenharmony_ci return false; 292f857971dSopenharmony_ci } 293f857971dSopenharmony_ci return true; 294f857971dSopenharmony_ci} 295f857971dSopenharmony_ci 296f857971dSopenharmony_civoid VirtualDeviceBuilder::Close() 297f857971dSopenharmony_ci{ 298f857971dSopenharmony_ci if (fd_ >= 0) { 299f857971dSopenharmony_ci if (ioctl(fd_, UI_DEV_DESTROY) < 0) { 300f857971dSopenharmony_ci FI_HILOGE("ioctl error:%{public}s", strerror(errno)); 301f857971dSopenharmony_ci } 302f857971dSopenharmony_ci if (close(fd_) != 0) { 303f857971dSopenharmony_ci FI_HILOGE("close error:%{public}s", strerror(errno)); 304f857971dSopenharmony_ci } 305f857971dSopenharmony_ci fd_ = -1; 306f857971dSopenharmony_ci } 307f857971dSopenharmony_ci} 308f857971dSopenharmony_ci 309f857971dSopenharmony_civoid VirtualDeviceBuilder::SetResolution(const ResolutionInfo &resolutionInfo) 310f857971dSopenharmony_ci{ 311f857971dSopenharmony_ci uinputAbs_.code = resolutionInfo.axisCode; 312f857971dSopenharmony_ci uinputAbs_.absinfo.resolution = resolutionInfo.absResolution; 313f857971dSopenharmony_ci absInit_.push_back(uinputAbs_); 314f857971dSopenharmony_ci} 315f857971dSopenharmony_ci 316f857971dSopenharmony_civoid VirtualDeviceBuilder::SetAbsValue(const AbsInfo &absInfo) 317f857971dSopenharmony_ci{ 318f857971dSopenharmony_ci uinputDev_.absmin[absInfo.code] = absInfo.minValue; 319f857971dSopenharmony_ci uinputDev_.absmax[absInfo.code] = absInfo.maxValue; 320f857971dSopenharmony_ci uinputDev_.absfuzz[absInfo.code] = absInfo.fuzz; 321f857971dSopenharmony_ci uinputDev_.absflat[absInfo.code] = absInfo.flat; 322f857971dSopenharmony_ci} 323f857971dSopenharmony_ci 324f857971dSopenharmony_ciconst std::vector<uint32_t> &VirtualDeviceBuilder::GetEventTypes() const 325f857971dSopenharmony_ci{ 326f857971dSopenharmony_ci return eventTypes_; 327f857971dSopenharmony_ci} 328f857971dSopenharmony_ci 329f857971dSopenharmony_ciconst std::vector<uint32_t> &VirtualDeviceBuilder::GetKeys() const 330f857971dSopenharmony_ci{ 331f857971dSopenharmony_ci return keys_; 332f857971dSopenharmony_ci} 333f857971dSopenharmony_ci 334f857971dSopenharmony_ciconst std::vector<uint32_t> &VirtualDeviceBuilder::GetProperties() const 335f857971dSopenharmony_ci{ 336f857971dSopenharmony_ci return properties_; 337f857971dSopenharmony_ci} 338f857971dSopenharmony_ci 339f857971dSopenharmony_ciconst std::vector<uint32_t> &VirtualDeviceBuilder::GetAbs() const 340f857971dSopenharmony_ci{ 341f857971dSopenharmony_ci return abs_; 342f857971dSopenharmony_ci} 343f857971dSopenharmony_ci 344f857971dSopenharmony_ciconst std::vector<uint32_t> &VirtualDeviceBuilder::GetRelBits() const 345f857971dSopenharmony_ci{ 346f857971dSopenharmony_ci return relBits_; 347f857971dSopenharmony_ci} 348f857971dSopenharmony_ci 349f857971dSopenharmony_ciconst std::vector<uint32_t> &VirtualDeviceBuilder::GetLeds() const 350f857971dSopenharmony_ci{ 351f857971dSopenharmony_ci return leds_; 352f857971dSopenharmony_ci} 353f857971dSopenharmony_ci 354f857971dSopenharmony_ciconst std::vector<uint32_t> &VirtualDeviceBuilder::GetRepeats() const 355f857971dSopenharmony_ci{ 356f857971dSopenharmony_ci return repeats_; 357f857971dSopenharmony_ci} 358f857971dSopenharmony_ci 359f857971dSopenharmony_ciconst std::vector<uint32_t> &VirtualDeviceBuilder::GetMiscellaneous() const 360f857971dSopenharmony_ci{ 361f857971dSopenharmony_ci return miscellaneous_; 362f857971dSopenharmony_ci} 363f857971dSopenharmony_ci 364f857971dSopenharmony_ciconst std::vector<uint32_t> &VirtualDeviceBuilder::GetSwitches() const 365f857971dSopenharmony_ci{ 366f857971dSopenharmony_ci return switches_; 367f857971dSopenharmony_ci} 368f857971dSopenharmony_ci 369f857971dSopenharmony_civoid VirtualDeviceBuilder::WaitFor(const char *path, const char *name) 370f857971dSopenharmony_ci{ 371f857971dSopenharmony_ci CALL_DEBUG_ENTER; 372f857971dSopenharmony_ci CHKPV(path); 373f857971dSopenharmony_ci if (!Utility::IsInteger(std::string(path))) { 374f857971dSopenharmony_ci std::cout << "Invalid argument to \'-w\', time duration of integer type is expected." << std::endl; 375f857971dSopenharmony_ci return; 376f857971dSopenharmony_ci } 377f857971dSopenharmony_ci WaitFor(name, std::atoi(path)); 378f857971dSopenharmony_ci} 379f857971dSopenharmony_ci 380f857971dSopenharmony_civoid VirtualDeviceBuilder::WaitFor(const char *name, int32_t timeout) 381f857971dSopenharmony_ci{ 382f857971dSopenharmony_ci CHKPV(name); 383f857971dSopenharmony_ci if (timeout < MINIMUM_WAIT_TIME_ALLOWED) { 384f857971dSopenharmony_ci std::cout << "Minimum wait time is " << MINIMUM_WAIT_TIME_ALLOWED << ", no wait." << std::endl; 385f857971dSopenharmony_ci return; 386f857971dSopenharmony_ci } 387f857971dSopenharmony_ci if (timeout > MAXIMUM_WAIT_TIME_ALLOWED) { 388f857971dSopenharmony_ci std::cout << "Maximum wait time is " << MAXIMUM_WAIT_TIME_ALLOWED << ", set wait time to this." << std::endl; 389f857971dSopenharmony_ci timeout = MAXIMUM_WAIT_TIME_ALLOWED; 390f857971dSopenharmony_ci } 391f857971dSopenharmony_ci std::cout << "[" << name << "] wait for " << timeout << " milliseconds." << std::endl; 392f857971dSopenharmony_ci std::this_thread::sleep_for(std::chrono::milliseconds(timeout)); 393f857971dSopenharmony_ci} 394f857971dSopenharmony_ci 395f857971dSopenharmony_ciint32_t VirtualDeviceBuilder::ReadFile(const char *path, json &model) 396f857971dSopenharmony_ci{ 397f857971dSopenharmony_ci CALL_DEBUG_ENTER; 398f857971dSopenharmony_ci CHKPR(path, RET_ERR); 399f857971dSopenharmony_ci char realPath[PATH_MAX] {}; 400f857971dSopenharmony_ci 401f857971dSopenharmony_ci if (realpath(path, realPath) == nullptr) { 402f857971dSopenharmony_ci std::cout << "Invalid path: " << path << std::endl; 403f857971dSopenharmony_ci return RET_ERR; 404f857971dSopenharmony_ci } 405f857971dSopenharmony_ci if (Utility::GetFileSize(realPath) > MAXIMUM_FILESIZE_ALLOWED) { 406f857971dSopenharmony_ci std::cout << "File is too large" << std::endl; 407f857971dSopenharmony_ci return RET_ERR; 408f857971dSopenharmony_ci } 409f857971dSopenharmony_ci std::cout << "Read input data from \'" << realPath << "\'" << std::endl; 410f857971dSopenharmony_ci IfStreamWrap fileStream; 411f857971dSopenharmony_ci fileStream.ifStream = std::ifstream(std::string(realPath)); 412f857971dSopenharmony_ci if (!fileStream.IsOpen()) { 413f857971dSopenharmony_ci FI_HILOGE("Could not open the file"); 414f857971dSopenharmony_ci return RET_ERR; 415f857971dSopenharmony_ci } 416f857971dSopenharmony_ci model = nlohmann::json::parse(fileStream.ifStream, nullptr, false); 417f857971dSopenharmony_ci if (model.is_discarded()) { 418f857971dSopenharmony_ci FI_HILOGE("model parse failed"); 419f857971dSopenharmony_ci return RET_ERR; 420f857971dSopenharmony_ci } 421f857971dSopenharmony_ci return RET_OK; 422f857971dSopenharmony_ci} 423f857971dSopenharmony_ci 424f857971dSopenharmony_ciint32_t VirtualDeviceBuilder::ScanFor(std::function<bool(std::shared_ptr<VirtualDevice>)> pred, 425f857971dSopenharmony_ci std::vector<std::shared_ptr<VirtualDevice>> &vDevs) 426f857971dSopenharmony_ci{ 427f857971dSopenharmony_ci CALL_DEBUG_ENTER; 428f857971dSopenharmony_ci DIR *dir = opendir(DEV_INPUT_PATH.c_str()); 429f857971dSopenharmony_ci if (dir == nullptr) { 430f857971dSopenharmony_ci FI_HILOGE("Failed to open directory \'%{public}s\':%{public}s", DEV_INPUT_PATH.c_str(), strerror(errno)); 431f857971dSopenharmony_ci return RET_ERR; 432f857971dSopenharmony_ci } 433f857971dSopenharmony_ci struct dirent *dent; 434f857971dSopenharmony_ci 435f857971dSopenharmony_ci while ((dent = readdir(dir)) != nullptr) { 436f857971dSopenharmony_ci const std::string devNode { dent->d_name }; 437f857971dSopenharmony_ci const std::string devPath { DEV_INPUT_PATH + devNode }; 438f857971dSopenharmony_ci struct stat statbuf; 439f857971dSopenharmony_ci 440f857971dSopenharmony_ci if ((std::strcmp(dent->d_name, ".") == 0) || (std::strcmp(dent->d_name, "..") == 0)) { 441f857971dSopenharmony_ci continue; 442f857971dSopenharmony_ci } 443f857971dSopenharmony_ci if (stat(devPath.c_str(), &statbuf) != 0) { 444f857971dSopenharmony_ci continue; 445f857971dSopenharmony_ci } 446f857971dSopenharmony_ci if (!S_ISCHR(statbuf.st_mode)) { 447f857971dSopenharmony_ci continue; 448f857971dSopenharmony_ci } 449f857971dSopenharmony_ci auto vdev = std::make_shared<VirtualDevice>(devPath); 450f857971dSopenharmony_ci if (pred(vdev)) { 451f857971dSopenharmony_ci vDevs.push_back(vdev); 452f857971dSopenharmony_ci } 453f857971dSopenharmony_ci } 454f857971dSopenharmony_ci if (closedir(dir) != 0) { 455f857971dSopenharmony_ci FI_HILOGE("closedir error:%{public}s", strerror(errno)); 456f857971dSopenharmony_ci } 457f857971dSopenharmony_ci return RET_OK; 458f857971dSopenharmony_ci} 459f857971dSopenharmony_ci 460f857971dSopenharmony_cistd::shared_ptr<VirtualDevice> VirtualDeviceBuilder::Select( 461f857971dSopenharmony_ci std::vector<std::shared_ptr<VirtualDevice>> &vDevs, const char *name) 462f857971dSopenharmony_ci{ 463f857971dSopenharmony_ci CALL_DEBUG_ENTER; 464f857971dSopenharmony_ci if (vDevs.empty()) { 465f857971dSopenharmony_ci std::cout << "No " << name << "." << std::endl; 466f857971dSopenharmony_ci return nullptr; 467f857971dSopenharmony_ci } 468f857971dSopenharmony_ci auto vDev = vDevs.front(); 469f857971dSopenharmony_ci 470f857971dSopenharmony_ci if (vDevs.size() > 1) { 471f857971dSopenharmony_ci std::cout << "More than one " << name << " were found, please select one to clone:" << std::endl; 472f857971dSopenharmony_ci size_t index = 0; 473f857971dSopenharmony_ci 474f857971dSopenharmony_ci for (const auto &v : vDevs) { 475f857971dSopenharmony_ci std::cout << "[" << index << "]\t" << v->GetName() << std::endl; 476f857971dSopenharmony_ci ++index; 477f857971dSopenharmony_ci } 478f857971dSopenharmony_ci std::cout << "[>=" << index << "]\tQuit" << std::endl; 479f857971dSopenharmony_ci std::cin >> index; 480f857971dSopenharmony_ci if (index >= vDevs.size()) { 481f857971dSopenharmony_ci std::cout << "Selected index is out of range, quit." << std::endl; 482f857971dSopenharmony_ci return nullptr; 483f857971dSopenharmony_ci } 484f857971dSopenharmony_ci vDev = vDevs[index]; 485f857971dSopenharmony_ci } 486f857971dSopenharmony_ci return vDev; 487f857971dSopenharmony_ci} 488f857971dSopenharmony_ci 489f857971dSopenharmony_civoid VirtualDeviceBuilder::CopyProperties(const std::string &name, std::shared_ptr<VirtualDevice> vDev) 490f857971dSopenharmony_ci{ 491f857971dSopenharmony_ci CHKPV(vDev); 492f857971dSopenharmony_ci CopyIdentity(name, vDev); 493f857971dSopenharmony_ci CopyAbsInfo(vDev); 494f857971dSopenharmony_ci CopyEvents(vDev); 495f857971dSopenharmony_ci} 496f857971dSopenharmony_ci 497f857971dSopenharmony_civoid VirtualDeviceBuilder::CopyIdentity(const std::string &name, std::shared_ptr<VirtualDevice> vDev) 498f857971dSopenharmony_ci{ 499f857971dSopenharmony_ci CALL_DEBUG_ENTER; 500f857971dSopenharmony_ci CHKPV(vDev); 501f857971dSopenharmony_ci uinputDev_.id = vDev->GetInputId(); 502f857971dSopenharmony_ci if (strcpy_s(uinputDev_.name, sizeof(uinputDev_.name), name.c_str()) != EOK) { 503f857971dSopenharmony_ci FI_HILOGE("Invalid device name:\'%{public}s\'", name.c_str()); 504f857971dSopenharmony_ci } 505f857971dSopenharmony_ci} 506f857971dSopenharmony_ci 507f857971dSopenharmony_civoid VirtualDeviceBuilder::CopyAbsInfo(std::shared_ptr<VirtualDevice> vDev) 508f857971dSopenharmony_ci{ 509f857971dSopenharmony_ci CALL_DEBUG_ENTER; 510f857971dSopenharmony_ci CHKPV(vDev); 511f857971dSopenharmony_ci for (size_t abs = ABS_X; abs < ABS_CNT; ++abs) { 512f857971dSopenharmony_ci struct uinput_abs_setup absSetup { 513f857971dSopenharmony_ci .code = static_cast<__u16>(abs), 514f857971dSopenharmony_ci }; 515f857971dSopenharmony_ci if (!vDev->QueryAbsInfo(abs, absSetup.absinfo)) { 516f857971dSopenharmony_ci FI_HILOGE("Failed to get abs info for axis %{public}zu", abs); 517f857971dSopenharmony_ci continue; 518f857971dSopenharmony_ci } 519f857971dSopenharmony_ci if (absSetup.absinfo.value == 0 && absSetup.absinfo.minimum == 0 && 520f857971dSopenharmony_ci absSetup.absinfo.maximum <= absSetup.absinfo.minimum && absSetup.absinfo.fuzz == 0 && 521f857971dSopenharmony_ci absSetup.absinfo.flat == 0 && absSetup.absinfo.resolution == 0) { 522f857971dSopenharmony_ci continue; 523f857971dSopenharmony_ci } 524f857971dSopenharmony_ci absInit_.push_back(absSetup); 525f857971dSopenharmony_ci uinputDev_.absmin[abs] = absSetup.absinfo.minimum; 526f857971dSopenharmony_ci uinputDev_.absmax[abs] = absSetup.absinfo.maximum; 527f857971dSopenharmony_ci uinputDev_.absfuzz[abs] = absSetup.absinfo.fuzz; 528f857971dSopenharmony_ci uinputDev_.absflat[abs] = absSetup.absinfo.flat; 529f857971dSopenharmony_ci } 530f857971dSopenharmony_ci} 531f857971dSopenharmony_ci 532f857971dSopenharmony_civoid VirtualDeviceBuilder::CopyEvents(std::shared_ptr<VirtualDevice> vDev) 533f857971dSopenharmony_ci{ 534f857971dSopenharmony_ci CALL_DEBUG_ENTER; 535f857971dSopenharmony_ci CHKPV(vDev); 536f857971dSopenharmony_ci for (uint32_t ev = EV_SYN; ev < EV_MAX; ++ev) { 537f857971dSopenharmony_ci if (vDev->SupportEventType(ev)) { 538f857971dSopenharmony_ci eventTypes_.push_back(ev); 539f857971dSopenharmony_ci } 540f857971dSopenharmony_ci } 541f857971dSopenharmony_ci for (uint32_t key = KEY_ESC; key < KEY_MAX; ++key) { 542f857971dSopenharmony_ci if (vDev->SupportKey(key)) { 543f857971dSopenharmony_ci keys_.push_back(key); 544f857971dSopenharmony_ci } 545f857971dSopenharmony_ci } 546f857971dSopenharmony_ci for (uint32_t abs = ABS_X; abs < ABS_MAX; ++abs) { 547f857971dSopenharmony_ci if (vDev->SupportAbs(abs)) { 548f857971dSopenharmony_ci abs_.push_back(abs); 549f857971dSopenharmony_ci } 550f857971dSopenharmony_ci } 551f857971dSopenharmony_ci for (uint32_t rel = REL_X; rel < REL_MAX; ++rel) { 552f857971dSopenharmony_ci if (vDev->SupportRel(rel)) { 553f857971dSopenharmony_ci relBits_.push_back(rel); 554f857971dSopenharmony_ci } 555f857971dSopenharmony_ci } 556f857971dSopenharmony_ci for (uint32_t msc = MSC_SERIAL; msc < MSC_MAX; ++msc) { 557f857971dSopenharmony_ci if (vDev->SupportMsc(msc)) { 558f857971dSopenharmony_ci miscellaneous_.push_back(msc); 559f857971dSopenharmony_ci } 560f857971dSopenharmony_ci } 561f857971dSopenharmony_ci for (uint32_t led = LED_NUML; led < LED_MAX; ++led) { 562f857971dSopenharmony_ci if (vDev->SupportLed(led)) { 563f857971dSopenharmony_ci leds_.push_back(led); 564f857971dSopenharmony_ci } 565f857971dSopenharmony_ci } 566f857971dSopenharmony_ci for (uint32_t rep = REP_DELAY; rep < REP_MAX; ++rep) { 567f857971dSopenharmony_ci if (vDev->SupportRep(rep)) { 568f857971dSopenharmony_ci repeats_.push_back(rep); 569f857971dSopenharmony_ci } 570f857971dSopenharmony_ci } 571f857971dSopenharmony_ci for (uint32_t prop = INPUT_PROP_POINTER; prop < INPUT_PROP_MAX; ++prop) { 572f857971dSopenharmony_ci if (vDev->SupportProperty(prop)) { 573f857971dSopenharmony_ci properties_.push_back(prop); 574f857971dSopenharmony_ci } 575f857971dSopenharmony_ci } 576f857971dSopenharmony_ci} 577f857971dSopenharmony_ci} // namespace DeviceStatus 578f857971dSopenharmony_ci} // namespace Msdp 579f857971dSopenharmony_ci} // namespace OHOS