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 "virtual_device.h" 17 18#include <iostream> 19#include <map> 20 21#include <unistd.h> 22 23#include "devicestatus_define.h" 24#include "fi_log.h" 25 26#undef LOG_TAG 27#define LOG_TAG "VirtualDevice" 28 29namespace OHOS { 30namespace Msdp { 31namespace DeviceStatus { 32namespace { 33constexpr size_t DEFAULT_BUF_SIZE { 1024 }; 34constexpr int32_t MINIMUM_INTERVAL_ALLOWED { 1 }; 35constexpr int32_t MAXIMUM_INTERVAL_ALLOWED { 100 }; 36} // namespace 37 38VirtualDevice::VirtualDevice(const std::string &node) 39{ 40 inputDev_ = std::make_unique<VInputDevice>(node); 41 inputDev_->Open(); 42} 43 44bool VirtualDevice::FindDeviceNode(const std::string &name, std::string &node) 45{ 46 CALL_DEBUG_ENTER; 47 std::map<std::string, std::string> nodes; 48 GetInputDeviceNodes(nodes); 49 FI_HILOGD("There are %{public}zu device nodes", nodes.size()); 50 51 std::map<std::string, std::string>::const_iterator cItr = nodes.find(name); 52 if (cItr == nodes.cend()) { 53 FI_HILOGE("No virtual stylus were found"); 54 return false; 55 } 56 FI_HILOGD("Node name : \'%{public}s\'", cItr->second.c_str()); 57 std::ostringstream ss; 58 ss << "/dev/input/" << cItr->second; 59 node = ss.str(); 60 return true; 61} 62 63void VirtualDevice::Execute(std::vector<std::string> &results) 64{ 65 CALL_DEBUG_ENTER; 66 char buffer[DEFAULT_BUF_SIZE] {}; 67 FILE *pin = popen("cat /proc/bus/input/devices", "r"); 68 if (pin == nullptr) { 69 FI_HILOGE("Failed to popen command"); 70 return; 71 } 72 while (!feof(pin)) { 73 if (fgets(buffer, sizeof(buffer), pin) != nullptr) { 74 results.push_back(buffer); 75 } 76 } 77 FI_HILOGD("Close phandle"); 78 pclose(pin); 79} 80 81void VirtualDevice::GetInputDeviceNodes(std::map<std::string, std::string> &nodes) 82{ 83 CALL_DEBUG_ENTER; 84 std::vector<std::string> results; 85 Execute(results); 86 if (results.empty()) { 87 FI_HILOGE("Failed to list devices"); 88 return; 89 } 90 const std::string kname { "Name=\"" }; 91 const std::string kevent { "event" }; 92 std::string name; 93 for (const auto &res : results) { 94 FI_HILOGD("res:%{public}s", res.c_str()); 95 if (res[0] == 'N') { 96 std::string::size_type spos = res.find(kname); 97 if (spos != std::string::npos) { 98 spos += kname.size(); 99 std::string::size_type tpos = res.find("\"", spos); 100 if (tpos != std::string::npos) { 101 name = res.substr(spos, tpos - spos); 102 } 103 } 104 } else if (!name.empty() && (res[0] == 'H')) { 105 std::string::size_type spos = res.find(kevent); 106 if (spos != std::string::npos) { 107 std::map<std::string, std::string>::const_iterator cItr = nodes.find(name); 108 if (cItr != nodes.end()) { 109 nodes.erase(cItr); 110 } 111 std::string::size_type tpos = spos + kevent.size(); 112 while (std::isalnum(res[tpos])) { 113 ++tpos; 114 } 115 auto [_, ret] = nodes.emplace(name, res.substr(spos, tpos - spos)); 116 if (!ret) { 117 FI_HILOGW("name is duplicated"); 118 } 119 name.clear(); 120 } 121 } 122 } 123} 124 125int32_t VirtualDevice::SendEvent(uint16_t type, uint16_t code, int32_t value) 126{ 127 CALL_DEBUG_ENTER; 128 CHKPR(inputDev_, RET_ERR); 129 inputDev_->SendEvent(type, code, value); 130 131 if ((type == EV_SYN) && (code == SYN_REPORT)) { 132 std::this_thread::sleep_for(std::chrono::milliseconds(minimumInterval_)); 133 } 134 return RET_OK; 135} 136 137std::string VirtualDevice::GetName() const 138{ 139 if (!name_.empty()) { 140 return name_; 141 } 142 if (inputDev_ != nullptr) { 143 return inputDev_->GetName(); 144 } 145 return {}; 146} 147 148void VirtualDevice::SetMinimumInterval(int32_t interval) 149{ 150 minimumInterval_ = std::max(MINIMUM_INTERVAL_ALLOWED, std::min(interval, MAXIMUM_INTERVAL_ALLOWED)); 151} 152} // namespace DeviceStatus 153} // namespace Msdp 154} // namespace OHOS