1 /*
2  * Copyright (c) 2021-2024 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 <securec.h>
19 #include <unistd.h>
20 
21 #include "constants_dinput.h"
22 #include "dinput_log.h"
23 #include "hidumper.h"
24 #include "dinput_utils_tool.h"
25 
26 namespace OHOS {
27 namespace DistributedHardware {
28 namespace DistributedInput {
29 namespace {
30     constexpr uint32_t ABS_MIN_POS = 1;
31     constexpr uint32_t ABS_MAX_POS = 2;
32     constexpr uint32_t ABS_FUZZ_POS = 3;
33     constexpr uint32_t ABS_FLAT_POS = 4;
34     constexpr uint32_t SLEEP_TIME_US = 10 * 1000;
35 }
VirtualDevice(const InputDevice & event)36 VirtualDevice::VirtualDevice(const InputDevice &event) : deviceName_(event.name), busType_(event.bus),
37     vendorId_(event.vendor), productId_(event.product), version_(event.version), classes_(event.classes)
38 {
39     DHLOGI("VirtualDevice ctor!");
40 }
41 
~VirtualDevice()42 VirtualDevice::~VirtualDevice()
43 {
44     if (fd_ >= 0) {
45         ioctl(fd_, UI_DEV_DESTROY);
46         close(fd_);
47         fd_ = -1;
48     }
49 }
50 
DoIoctl(int32_t fd,int32_t request,const uint32_t value)51 bool VirtualDevice::DoIoctl(int32_t fd, int32_t request, const uint32_t value)
52 {
53     int rc = ioctl(fd, request, value);
54     if (rc < 0) {
55         DHLOGE("ioctl failed");
56         return false;
57     }
58     return true;
59 }
60 
CreateKey(const InputDevice & inputDevice)61 bool VirtualDevice::CreateKey(const InputDevice &inputDevice)
62 {
63     auto fun = [this](int32_t uiSet, const std::vector<uint32_t>& list) -> bool {
64         for (uint32_t evt_type : list) {
65             if (!DoIoctl(fd_, uiSet, evt_type)) {
66                 DHLOGE("Error setting event type: %{public}u", evt_type);
67                 return false;
68             }
69         }
70         return true;
71     };
72     std::map<int32_t, std::vector<uint32_t>> evt_type;
73     evt_type[UI_SET_EVBIT] = inputDevice.eventTypes;
74     evt_type[UI_SET_KEYBIT] = inputDevice.eventKeys;
75     evt_type[UI_SET_PROPBIT] = inputDevice.properties;
76     evt_type[UI_SET_ABSBIT] = inputDevice.absTypes;
77     evt_type[UI_SET_RELBIT] = inputDevice.relTypes;
78 
79     evt_type[UI_SET_MSCBIT] = inputDevice.miscellaneous;
80     evt_type[UI_SET_LEDBIT] = inputDevice.leds;
81     evt_type[UI_SET_SWBIT] = inputDevice.switchs;
82     evt_type[UI_SET_FFBIT] = inputDevice.repeats;
83 
84     for (auto &it : evt_type) {
85         if (!fun(it.first, it.second)) {
86             return false;
87         }
88     }
89     return true;
90 }
91 
SetABSInfo(struct uinput_user_dev & inputUserDev,const InputDevice & inputDevice)92 void VirtualDevice::SetABSInfo(struct uinput_user_dev &inputUserDev, const InputDevice &inputDevice)
93 {
94     DHLOGI("SetABSInfo!");
95     for (auto item : inputDevice.absInfos) {
96         int absCode = item.first;
97         std::vector<int32_t> absInfo = item.second;
98         DHLOGI("SetABSInfo nodeName: %{public}s, absCode: %{public}d, absMin: %{public}d, absMax: %{public}d, "
99             "absFuzz: %{public}d, absFlat: %{public}d", inputDevice.name.c_str(), absCode, absInfo[ABS_MIN_POS],
100             absInfo[ABS_MAX_POS], absInfo[ABS_FUZZ_POS], absInfo[ABS_FLAT_POS]);
101         if (absInfo[ABS_MAX_POS] < absInfo[ABS_MIN_POS]) {
102             DHLOGE("NodeName: %{public}s, absCode: %{public}d, attributes is invalid.", inputDevice.name.c_str(),
103                 absCode);
104             continue;
105         }
106         inputUserDev.absmin[absCode] = absInfo[ABS_MIN_POS];
107         inputUserDev.absmax[absCode] = absInfo[ABS_MAX_POS];
108         inputUserDev.absfuzz[absCode] = absInfo[ABS_FUZZ_POS];
109         inputUserDev.absflat[absCode] = absInfo[ABS_FLAT_POS];
110     }
111 }
112 
SetPhys(const std::string & deviceName,const std::string & dhId)113 bool VirtualDevice::SetPhys(const std::string &deviceName, const std::string &dhId)
114 {
115     std::string phys;
116     phys.append(deviceName).append(pid_).append(VIR_NODE_PID_SPLIT).append(pid_).append(VIR_NODE_SPLIT)
117         .append(netWorkId_).append(VIR_NODE_SPLIT).append(dhId);
118 
119     if (ioctl(fd_, UI_SET_PHYS, phys.c_str()) < 0) {
120         return false;
121     }
122     return true;
123 }
124 
SetUp(const InputDevice & inputDevice,const std::string & devId,const std::string & dhId)125 bool VirtualDevice::SetUp(const InputDevice &inputDevice, const std::string &devId, const std::string &dhId)
126 {
127     fd_ = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
128     if (fd_ < 0) {
129         DHLOGE("Failed to open uinput");
130         return false;
131     }
132 
133     deviceName_ = VIRTUAL_DEVICE_NAME + deviceName_;
134     if (deviceName_.size() > MAX_SIZE_OF_DEVICE_NAME) {
135         deviceName_ = deviceName_.substr(0, MAX_SIZE_OF_DEVICE_NAME);
136     }
137     if (strncpy_s(dev_.name, sizeof(dev_.name), deviceName_.c_str(), deviceName_.size()) != 0) {
138         return false;
139     }
140     HiDumper::GetInstance().SaveNodeInfo(devId, deviceName_, dhId);
141     dev_.id.bustype = busType_;
142     dev_.id.vendor = vendorId_;
143     dev_.id.product = productId_;
144     dev_.id.version = version_;
145 
146     if (!SetPhys(deviceName_, dhId)) {
147         DHLOGE("Failed to set PHYS!");
148         return false;
149     }
150 
151     if (!CreateKey(inputDevice)) {
152         DHLOGE("Failed to create KeyValue");
153         return false;
154     }
155 
156     SetABSInfo(dev_, inputDevice);
157 
158     if (write(fd_, &dev_, sizeof(dev_)) < 0) {
159         DHLOGE("Unable to set input device info");
160         return false;
161     }
162     int ret = ioctl(fd_, UI_DEV_CREATE);
163     if (ret < 0) {
164         DHLOGE("Unable to create input device, fd: %{public}d, ret= %{public}d", fd_, ret);
165         return false;
166     }
167     DHLOGI("create fd %{public}d", fd_);
168     usleep(SLEEP_TIME_US);
169     char sysfsDeviceName[16] = {0};
170     if (ioctl(fd_, UI_GET_SYSNAME(sizeof(sysfsDeviceName)), sysfsDeviceName) < 0) {
171         DHLOGE("Unable to get input device name");
172         CloseFd(fd_);
173         return false;
174     }
175     DHLOGI("get input device name: %{public}s, fd: %{public}d", GetAnonyString(sysfsDeviceName).c_str(), fd_);
176     return true;
177 }
178 
InjectInputEvent(const input_event & event)179 bool VirtualDevice::InjectInputEvent(const input_event &event)
180 {
181     if (write(fd_, &event, sizeof(event)) < static_cast<ssize_t>(sizeof(event))) {
182         DHLOGE("could not inject event, removed? (fd: %{public}d", fd_);
183         return false;
184     }
185     RecordEventLog(event);
186     return true;
187 }
188 
SetNetWorkId(const std::string & netWorkId)189 void VirtualDevice::SetNetWorkId(const std::string &netWorkId)
190 {
191     DHLOGI("SetNetWorkId %{public}s\n", GetAnonyString(netWorkId).c_str());
192     netWorkId_ = netWorkId;
193 }
194 
SetPath(const std::string & path)195 void VirtualDevice::SetPath(const std::string &path)
196 {
197     path_ = path;
198 }
199 
GetNetWorkId()200 std::string VirtualDevice::GetNetWorkId()
201 {
202     return netWorkId_;
203 }
204 
GetPath()205 std::string VirtualDevice::GetPath()
206 {
207     return path_;
208 }
209 
GetClasses()210 uint16_t VirtualDevice::GetClasses()
211 {
212     return classes_;
213 }
214 
RecordEventLog(const input_event & event)215 void VirtualDevice::RecordEventLog(const input_event &event)
216 {
217     std::string eventType = "";
218     switch (event.type) {
219         case EV_KEY:
220             eventType = "EV_KEY";
221             break;
222         case EV_REL:
223             eventType = "EV_REL";
224             break;
225         case EV_ABS:
226             eventType = "EV_ABS";
227             break;
228         default:
229             eventType = "other type " + std::to_string(event.type);
230             break;
231     }
232     DHLOGD("4.E2E-Test Source write event into input driver, EventType: %{public}s, Code: %{public}d, "
233         "Value: %{public}d, Sec: %ld, Sec1: %ld", eventType.c_str(), event.code, event.value, event.input_event_sec,
234         event.input_event_usec);
235 }
236 
GetDeviceFd()237 int32_t VirtualDevice::GetDeviceFd()
238 {
239     return fd_;
240 }
241 
GetDeviceType()242 uint16_t VirtualDevice::GetDeviceType()
243 {
244     return classes_;
245 }
246 } // namespace DistributedInput
247 } // namespace DistributedHardware
248 } // namespace OHOS
249