• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
77     evt_type[UI_SET_MSCBIT] = inputDevice.miscellaneous;
78     evt_type[UI_SET_LEDBIT] = inputDevice.leds;
79     evt_type[UI_SET_SWBIT] = inputDevice.switchs;
80     evt_type[UI_SET_FFBIT] = inputDevice.repeats;
81 
82     for (auto &it : evt_type) {
83         if (!fun(it.first, it.second)) {
84             return false;
85         }
86     }
87     return true;
88 }
89 
SetABSInfo(struct uinput_user_dev & inputUserDev,const InputDevice & inputDevice)90 void VirtualDevice::SetABSInfo(struct uinput_user_dev &inputUserDev, const InputDevice &inputDevice)
91 {
92     DHLOGI("SetABSInfo!");
93     for (const auto item : inputDevice.absInfos) {
94         int absCode = item.first;
95         std::vector<int32_t> absInfo = item.second;
96         DHLOGI("SetABSInfo nodeName: %s, absCode: %d, absMin: %d, absMax: %d, absFuzz: %d, absFlat: %d",
97             inputDevice.name.c_str(), absCode, absInfo[ABS_MIN_POS], absInfo[ABS_MAX_POS], absInfo[ABS_FUZZ_POS],
98             absInfo[ABS_FLAT_POS]);
99         if (absInfo[ABS_MAX_POS] < absInfo[ABS_MIN_POS]) {
100             DHLOGE("NodeName: %s, absCode: %d, attributes is invalid.", inputDevice.name.c_str(), absCode);
101             continue;
102         }
103         inputUserDev.absmin[absCode] = absInfo[ABS_MIN_POS];
104         inputUserDev.absmax[absCode] = absInfo[ABS_MAX_POS];
105         inputUserDev.absfuzz[absCode] = absInfo[ABS_FUZZ_POS];
106         inputUserDev.absflat[absCode] = absInfo[ABS_FLAT_POS];
107     }
108 }
109 
SetPhys(const std::string & deviceName,const std::string & dhId)110 bool VirtualDevice::SetPhys(const std::string &deviceName, const std::string &dhId)
111 {
112     std::string phys;
113     phys.append(deviceName).append(pid_).append(VIR_NODE_PID_SPLIT).append(pid_).append(VIR_NODE_SPLIT)
114         .append(netWorkId_).append(VIR_NODE_SPLIT).append(dhId);
115 
116     if (ioctl(fd_, UI_SET_PHYS, phys.c_str()) < 0) {
117         return false;
118     }
119     return true;
120 }
121 
SetUp(const InputDevice & inputDevice,const std::string & devId,const std::string & dhId)122 bool VirtualDevice::SetUp(const InputDevice &inputDevice, const std::string &devId, const std::string &dhId)
123 {
124     fd_ = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
125     if (fd_ < 0) {
126         DHLOGE("Failed to open uinput");
127         return false;
128     }
129 
130     deviceName_ = VIRTUAL_DEVICE_NAME + deviceName_;
131     if (deviceName_.size() > MAX_SIZE_OF_DEVICE_NAME) {
132         deviceName_ = deviceName_.substr(0, MAX_SIZE_OF_DEVICE_NAME);
133     }
134     if (strncpy_s(dev_.name, sizeof(dev_.name), deviceName_.c_str(), deviceName_.size()) != 0) {
135         return false;
136     }
137     HiDumper::GetInstance().SaveNodeInfo(devId, deviceName_, dhId);
138     dev_.id.bustype = busType_;
139     dev_.id.vendor = vendorId_;
140     dev_.id.product = productId_;
141     dev_.id.version = version_;
142 
143     if (!SetPhys(deviceName_, dhId)) {
144         DHLOGE("Failed to set PHYS!");
145         return false;
146     }
147 
148     if (!CreateKey(inputDevice)) {
149         DHLOGE("Failed to create KeyValue");
150         return false;
151     }
152 
153     SetABSInfo(dev_, inputDevice);
154 
155     if (write(fd_, &dev_, sizeof(dev_)) < 0) {
156         DHLOGE("Unable to set input device info");
157         return false;
158     }
159     int ret = ioctl(fd_, UI_DEV_CREATE);
160     if (ret < 0) {
161         DHLOGE("Unable to create input device, fd: %d, ret= %d", fd_, ret);
162         return false;
163     }
164     DHLOGI("create fd %d", fd_);
165 
166     char sysfsDeviceName[16] = {0};
167     if (ioctl(fd_, UI_GET_SYSNAME(sizeof(sysfsDeviceName)), sysfsDeviceName) < 0) {
168         DHLOGE("Unable to get input device name");
169     }
170     DHLOGI("get input device name: %s, fd: %d", GetAnonyString(sysfsDeviceName).c_str(), fd_);
171     return true;
172 }
173 
InjectInputEvent(const input_event & event)174 bool VirtualDevice::InjectInputEvent(const input_event &event)
175 {
176     if (write(fd_, &event, sizeof(event)) < static_cast<ssize_t>(sizeof(event))) {
177         DHLOGE("could not inject event, removed? (fd: %d", fd_);
178         return false;
179     }
180     RecordEventLog(event);
181     return true;
182 }
183 
SetNetWorkId(const std::string & netWorkId)184 void VirtualDevice::SetNetWorkId(const std::string &netWorkId)
185 {
186     DHLOGI("SetNetWorkId %s\n", GetAnonyString(netWorkId).c_str());
187     netWorkId_ = netWorkId;
188 }
189 
SetPath(const std::string & path)190 void VirtualDevice::SetPath(const std::string &path)
191 {
192     path_ = path;
193 }
194 
GetNetWorkId()195 std::string VirtualDevice::GetNetWorkId()
196 {
197     return netWorkId_;
198 }
199 
GetPath()200 std::string VirtualDevice::GetPath()
201 {
202     return path_;
203 }
204 
GetClasses()205 uint16_t VirtualDevice::GetClasses()
206 {
207     return classes_;
208 }
209 
RecordEventLog(const input_event & event)210 void VirtualDevice::RecordEventLog(const input_event &event)
211 {
212     std::string eventType = "";
213     switch (event.type) {
214         case EV_KEY:
215             eventType = "EV_KEY";
216             break;
217         case EV_REL:
218             eventType = "EV_REL";
219             break;
220         case EV_ABS:
221             eventType = "EV_ABS";
222             break;
223         default:
224             eventType = "other type " + std::to_string(event.type);
225             break;
226     }
227     DHLOGD("4.E2E-Test Source write event into input driver, EventType: %s, Code: %d, Value: %d, Sec: %ld, Sec1: %ld",
228         eventType.c_str(), event.code, event.value, event.input_event_sec, event.input_event_usec);
229 }
230 
GetDeviceFd()231 int32_t VirtualDevice::GetDeviceFd()
232 {
233     return fd_;
234 }
235 
GetDeviceType()236 uint16_t VirtualDevice::GetDeviceType()
237 {
238     return classes_;
239 }
240 } // namespace DistributedInput
241 } // namespace DistributedHardware
242 } // namespace OHOS
243