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