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