1 /*
2  * Copyright (c) 2021-2022 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 <fcntl.h>
19 #include <securec.h>
20 #include <unistd.h>
21 
22 #include "mmi_log.h"
23 
24 #undef MMI_LOG_TAG
25 #define MMI_LOG_TAG "VirtualDevice"
26 
27 namespace OHOS {
28 namespace MMI {
29 namespace {
30 using namespace OHOS::HiviewDFX;
31 constexpr uint32_t MAX_NAME_LENGTH { 80 };
32 
DoIoctl(int32_t fd,int32_t request,const uint32_t value)33 bool DoIoctl(int32_t fd, int32_t request, const uint32_t value)
34 {
35     int32_t rc = ioctl(fd, request, value);
36     if (rc < 0) {
37         MMI_HILOGE("Failed to ioctl");
38         return false;
39     }
40     return true;
41 }
42 } // namespace
43 
VirtualDevice(const char * deviceName,uint16_t productId)44 VirtualDevice::VirtualDevice(const char *deviceName, uint16_t productId)
45     : deviceName_(deviceName),
46       busType_(BUS_USB),
47       vendorId_(0x6006),
48       productId_(productId),
49       version_(1) {}
50 
~VirtualDevice()51 VirtualDevice::~VirtualDevice()
52 {
53     if (fd_ >= 0) {
54         ioctl(fd_, UI_DEV_DESTROY);
55         close(fd_);
56         fd_ = -1;
57     }
58 }
59 
SetUp()60 bool VirtualDevice::SetUp()
61 {
62     fd_ = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
63     if (fd_ < 0) {
64         MMI_HILOGE("Failed to open uinput");
65         return false;
66     }
67     for (const auto &item : GetEventTypes()) {
68         if (!DoIoctl(fd_, UI_SET_EVBIT, item)) {
69             MMI_HILOGE("Error setting event type:%{public}u", item);
70             return false;
71         }
72     }
73     for (const auto &item : GetKeys()) {
74         if (!DoIoctl(fd_, UI_SET_KEYBIT, item)) {
75             MMI_HILOGE("Error setting key:%{public}u", item);
76             return false;
77         }
78     }
79     for (const auto &item :  GetProperties()) {
80         if (!DoIoctl(fd_, UI_SET_PROPBIT, item)) {
81             MMI_HILOGE("Error setting property:%{public}u", item);
82             return false;
83         }
84     }
85     for (const auto &item : GetAbs()) {
86         if (!DoIoctl(fd_, UI_SET_ABSBIT, item)) {
87             MMI_HILOGE("Error setting property:%{public}u", item);
88             return false;
89         }
90     }
91     for (const auto &item : GetRelBits()) {
92         if (!DoIoctl(fd_, UI_SET_RELBIT, item)) {
93             MMI_HILOGE("Error setting rel:%{public}u", item);
94             return false;
95         }
96     }
97 
98     return SetUpExt();
99 }
100 
SetUpExt()101 bool VirtualDevice::SetUpExt()
102 {
103     errno_t ret = strncpy_s(dev_.name, MAX_NAME_LENGTH, deviceName_, sizeof(dev_.name));
104     if (ret != EOK) {
105         MMI_HILOGE("Failed to copy deviceName");
106         return false;
107     }
108     dev_.id.bustype = busType_;
109     dev_.id.vendor = vendorId_;
110     dev_.id.product = productId_;
111     dev_.id.version = version_;
112     if (write(fd_, &dev_, sizeof(dev_)) < 0) {
113         MMI_HILOGE("Unable to set input device info");
114         return false;
115     }
116     if (ioctl(fd_, UI_DEV_CREATE) < 0) {
117         MMI_HILOGE("Unable to create input device");
118         return false;
119     }
120     return true;
121 }
122 
EmitEvent(uint16_t type,uint16_t code,uint32_t value) const123 bool VirtualDevice::EmitEvent(uint16_t type, uint16_t code, uint32_t value) const
124 {
125     struct input_event event {};
126     event.type = type;
127     event.code = code;
128     event.value = value;
129 #ifndef __MUSL__
130     gettimeofday(&event.time, nullptr);
131 #endif
132     if (write(fd_, &event, sizeof(event)) < static_cast<ssize_t>(sizeof(event))) {
133         MMI_HILOGE("Event write failed");
134         return false;
135     }
136     return true;
137 }
138 
GetEventTypes() const139 const std::vector<uint32_t> &VirtualDevice::GetEventTypes() const
140 {
141     static const std::vector<uint32_t> evtTypes {};
142     return evtTypes;
143 }
144 
GetKeys() const145 const std::vector<uint32_t> &VirtualDevice::GetKeys() const
146 {
147     static const std::vector<uint32_t> keys {};
148     return keys;
149 }
150 
GetProperties() const151 const std::vector<uint32_t> &VirtualDevice::GetProperties() const
152 {
153     static const std::vector<uint32_t> properties {};
154     return properties;
155 }
156 
GetAbs() const157 const std::vector<uint32_t> &VirtualDevice::GetAbs() const
158 {
159     static const std::vector<uint32_t> abs {};
160     return abs;
161 }
162 
GetRelBits() const163 const std::vector<uint32_t> &VirtualDevice::GetRelBits() const
164 {
165     static const std::vector<uint32_t> relBits {};
166     return relBits;
167 }
168 }
169 }
170