1c29fa5a6Sopenharmony_ci/*
2c29fa5a6Sopenharmony_ci * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3c29fa5a6Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4c29fa5a6Sopenharmony_ci * you may not use this file except in compliance with the License.
5c29fa5a6Sopenharmony_ci * You may obtain a copy of the License at
6c29fa5a6Sopenharmony_ci *
7c29fa5a6Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8c29fa5a6Sopenharmony_ci *
9c29fa5a6Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10c29fa5a6Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11c29fa5a6Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12c29fa5a6Sopenharmony_ci * See the License for the specific language governing permissions and
13c29fa5a6Sopenharmony_ci * limitations under the License.
14c29fa5a6Sopenharmony_ci */
15c29fa5a6Sopenharmony_ci
16c29fa5a6Sopenharmony_ci#include "device.h"
17c29fa5a6Sopenharmony_ci
18c29fa5a6Sopenharmony_ci#include <fcntl.h>
19c29fa5a6Sopenharmony_ci#include <unistd.h>
20c29fa5a6Sopenharmony_ci#include <sys/ioctl.h>
21c29fa5a6Sopenharmony_ci
22c29fa5a6Sopenharmony_ci#include <cstring>
23c29fa5a6Sopenharmony_ci#include <fstream>
24c29fa5a6Sopenharmony_ci#include <map>
25c29fa5a6Sopenharmony_ci#include <regex>
26c29fa5a6Sopenharmony_ci#include <sstream>
27c29fa5a6Sopenharmony_ci
28c29fa5a6Sopenharmony_ci#include <openssl/sha.h>
29c29fa5a6Sopenharmony_ci#include <securec.h>
30c29fa5a6Sopenharmony_ci
31c29fa5a6Sopenharmony_ci#include "devicestatus_define.h"
32c29fa5a6Sopenharmony_ci#include "devicestatus_errors.h"
33c29fa5a6Sopenharmony_ci#include "fi_log.h"
34c29fa5a6Sopenharmony_ci#include "if_stream_wrap.h"
35c29fa5a6Sopenharmony_ci#include "napi_constants.h"
36c29fa5a6Sopenharmony_ci#include "utility.h"
37c29fa5a6Sopenharmony_ci
38c29fa5a6Sopenharmony_ci#undef LOG_TAG
39c29fa5a6Sopenharmony_ci#define LOG_TAG "Device"
40c29fa5a6Sopenharmony_ci
41c29fa5a6Sopenharmony_cinamespace OHOS {
42c29fa5a6Sopenharmony_cinamespace Msdp {
43c29fa5a6Sopenharmony_cinamespace DeviceStatus {
44c29fa5a6Sopenharmony_cistruct Range {
45c29fa5a6Sopenharmony_ci    size_t start { 0 };
46c29fa5a6Sopenharmony_ci    size_t end { 0 };
47c29fa5a6Sopenharmony_ci};
48c29fa5a6Sopenharmony_ci
49c29fa5a6Sopenharmony_cinamespace {
50c29fa5a6Sopenharmony_ciconstexpr int32_t COMMENT_SUBSCRIPT { 0 };
51c29fa5a6Sopenharmony_ciconstexpr ssize_t MAX_FILE_SIZE_ALLOWED { 0x5000 };
52c29fa5a6Sopenharmony_ci
53c29fa5a6Sopenharmony_ciconst struct Range KEY_BLOCKS[] {
54c29fa5a6Sopenharmony_ci    { KEY_ESC, BTN_MISC },
55c29fa5a6Sopenharmony_ci    { KEY_OK, BTN_DPAD_UP },
56c29fa5a6Sopenharmony_ci    { KEY_ALS_TOGGLE, BTN_TRIGGER_HAPPY }
57c29fa5a6Sopenharmony_ci};
58c29fa5a6Sopenharmony_ci} // namespace
59c29fa5a6Sopenharmony_ci
60c29fa5a6Sopenharmony_ciDevice::Device(int32_t deviceId)
61c29fa5a6Sopenharmony_ci    : deviceId_(deviceId)
62c29fa5a6Sopenharmony_ci{}
63c29fa5a6Sopenharmony_ci
64c29fa5a6Sopenharmony_ciDevice::~Device()
65c29fa5a6Sopenharmony_ci{
66c29fa5a6Sopenharmony_ci    Close();
67c29fa5a6Sopenharmony_ci}
68c29fa5a6Sopenharmony_ci
69c29fa5a6Sopenharmony_ciint32_t Device::Open()
70c29fa5a6Sopenharmony_ci{
71c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
72c29fa5a6Sopenharmony_ci    char buf[PATH_MAX] {};
73c29fa5a6Sopenharmony_ci    if (realpath(devPath_.c_str(), buf) == nullptr) {
74c29fa5a6Sopenharmony_ci        FI_HILOGE("Not real path:%{private}s", devPath_.c_str());
75c29fa5a6Sopenharmony_ci        return RET_ERR;
76c29fa5a6Sopenharmony_ci    }
77c29fa5a6Sopenharmony_ci
78c29fa5a6Sopenharmony_ci    int32_t nRetries { 6 };
79c29fa5a6Sopenharmony_ci    for (;;) {
80c29fa5a6Sopenharmony_ci        Utility::ShowUserAndGroup();
81c29fa5a6Sopenharmony_ci        Utility::ShowFileAttributes(buf);
82c29fa5a6Sopenharmony_ci
83c29fa5a6Sopenharmony_ci        fd_ = open(buf, O_RDWR | O_NONBLOCK | O_CLOEXEC);
84c29fa5a6Sopenharmony_ci        if (fd_ < 0) {
85c29fa5a6Sopenharmony_ci            FI_HILOGE("Open device \'%{public}s\':%{public}s failed", buf, strerror(errno));
86c29fa5a6Sopenharmony_ci            if (nRetries-- > 0) {
87c29fa5a6Sopenharmony_ci                static constexpr int32_t DEFAULT_WAIT_TIME { 500 };
88c29fa5a6Sopenharmony_ci                std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_WAIT_TIME));
89c29fa5a6Sopenharmony_ci                FI_HILOGI("Retry opening the device \'%{public}s\'", buf);
90c29fa5a6Sopenharmony_ci            } else {
91c29fa5a6Sopenharmony_ci                return RET_ERR;
92c29fa5a6Sopenharmony_ci            }
93c29fa5a6Sopenharmony_ci        } else {
94c29fa5a6Sopenharmony_ci            FI_HILOGD("Successful opening \'%{public}s\'", buf);
95c29fa5a6Sopenharmony_ci            break;
96c29fa5a6Sopenharmony_ci        }
97c29fa5a6Sopenharmony_ci    }
98c29fa5a6Sopenharmony_ci    QueryDeviceInfo();
99c29fa5a6Sopenharmony_ci    QuerySupportedEvents();
100c29fa5a6Sopenharmony_ci    UpdateCapability();
101c29fa5a6Sopenharmony_ci    LoadDeviceConfig();
102c29fa5a6Sopenharmony_ci    return RET_OK;
103c29fa5a6Sopenharmony_ci}
104c29fa5a6Sopenharmony_ci
105c29fa5a6Sopenharmony_civoid Device::Close()
106c29fa5a6Sopenharmony_ci{
107c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
108c29fa5a6Sopenharmony_ci    if (fd_ >= 0) {
109c29fa5a6Sopenharmony_ci        if (close(fd_) < 0) {
110c29fa5a6Sopenharmony_ci            FI_HILOGE("Close fd failed, error:%{public}s, fd_:%{public}d", strerror(errno), fd_);
111c29fa5a6Sopenharmony_ci        }
112c29fa5a6Sopenharmony_ci        fd_ = -1;
113c29fa5a6Sopenharmony_ci    }
114c29fa5a6Sopenharmony_ci}
115c29fa5a6Sopenharmony_ci
116c29fa5a6Sopenharmony_civoid Device::Dispatch(const struct epoll_event &ev)
117c29fa5a6Sopenharmony_ci{
118c29fa5a6Sopenharmony_ci    if ((ev.events & EPOLLIN) == EPOLLIN) {
119c29fa5a6Sopenharmony_ci        FI_HILOGD("Input data received");
120c29fa5a6Sopenharmony_ci    } else if ((ev.events & (EPOLLHUP | EPOLLERR)) != 0) {
121c29fa5a6Sopenharmony_ci        FI_HILOGE("Epoll hangup, errno:%{public}s", strerror(errno));
122c29fa5a6Sopenharmony_ci    }
123c29fa5a6Sopenharmony_ci}
124c29fa5a6Sopenharmony_ci
125c29fa5a6Sopenharmony_civoid Device::QueryDeviceInfo()
126c29fa5a6Sopenharmony_ci{
127c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
128c29fa5a6Sopenharmony_ci    char buffer[PATH_MAX] = { 0 };
129c29fa5a6Sopenharmony_ci    int32_t rc = ioctl(fd_, EVIOCGNAME(sizeof(buffer) - 1), &buffer);
130c29fa5a6Sopenharmony_ci    if (rc < 0) {
131c29fa5a6Sopenharmony_ci        FI_HILOGE("Could not get device name, errno:%{public}s", strerror(errno));
132c29fa5a6Sopenharmony_ci    } else {
133c29fa5a6Sopenharmony_ci        name_.assign(buffer);
134c29fa5a6Sopenharmony_ci    }
135c29fa5a6Sopenharmony_ci
136c29fa5a6Sopenharmony_ci    struct input_id inputId;
137c29fa5a6Sopenharmony_ci    rc = ioctl(fd_, EVIOCGID, &inputId);
138c29fa5a6Sopenharmony_ci    if (rc < 0) {
139c29fa5a6Sopenharmony_ci        FI_HILOGE("Could not get device input id, errno:%{public}s", strerror(errno));
140c29fa5a6Sopenharmony_ci    } else {
141c29fa5a6Sopenharmony_ci        bus_ = inputId.bustype;
142c29fa5a6Sopenharmony_ci        product_ = inputId.product;
143c29fa5a6Sopenharmony_ci        vendor_ = inputId.vendor;
144c29fa5a6Sopenharmony_ci        version_ = inputId.version;
145c29fa5a6Sopenharmony_ci    }
146c29fa5a6Sopenharmony_ci
147c29fa5a6Sopenharmony_ci    errno_t ret = memset_s(buffer, sizeof(buffer), 0, sizeof(buffer));
148c29fa5a6Sopenharmony_ci    if (ret != EOK) {
149c29fa5a6Sopenharmony_ci        FI_HILOGE("Call memset_s failed");
150c29fa5a6Sopenharmony_ci        return;
151c29fa5a6Sopenharmony_ci    }
152c29fa5a6Sopenharmony_ci    rc = ioctl(fd_, EVIOCGPHYS(sizeof(buffer) - 1), &buffer);
153c29fa5a6Sopenharmony_ci    if (rc < 0) {
154c29fa5a6Sopenharmony_ci        FI_HILOGE("Could not get location:%{public}s", strerror(errno));
155c29fa5a6Sopenharmony_ci    } else {
156c29fa5a6Sopenharmony_ci        phys_.assign(buffer);
157c29fa5a6Sopenharmony_ci    }
158c29fa5a6Sopenharmony_ci    ret = memset_s(buffer, sizeof(buffer), 0, sizeof(buffer));
159c29fa5a6Sopenharmony_ci    if (ret != EOK) {
160c29fa5a6Sopenharmony_ci        FI_HILOGE("Call memset_s failed");
161c29fa5a6Sopenharmony_ci        return;
162c29fa5a6Sopenharmony_ci    }
163c29fa5a6Sopenharmony_ci    rc = ioctl(fd_, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer);
164c29fa5a6Sopenharmony_ci    if (rc < 0) {
165c29fa5a6Sopenharmony_ci        FI_HILOGE("Could not get uniq, errno:%{public}s", strerror(errno));
166c29fa5a6Sopenharmony_ci    } else {
167c29fa5a6Sopenharmony_ci        uniq_.assign(buffer);
168c29fa5a6Sopenharmony_ci    }
169c29fa5a6Sopenharmony_ci}
170c29fa5a6Sopenharmony_ci
171c29fa5a6Sopenharmony_civoid Device::GetEventMask(const std::string &eventName, uint32_t type,
172c29fa5a6Sopenharmony_ci    std::size_t arrayLength, uint8_t *whichBitMask) const
173c29fa5a6Sopenharmony_ci{
174c29fa5a6Sopenharmony_ci    int32_t rc = ioctl(fd_, EVIOCGBIT(type, arrayLength), whichBitMask);
175c29fa5a6Sopenharmony_ci    if (rc < 0) {
176c29fa5a6Sopenharmony_ci        FI_HILOGE("Could not get %{public}s events mask:%{public}s", eventName.c_str(), strerror(errno));
177c29fa5a6Sopenharmony_ci    }
178c29fa5a6Sopenharmony_ci}
179c29fa5a6Sopenharmony_ci
180c29fa5a6Sopenharmony_civoid Device::GetPropMask(const std::string &eventName, std::size_t arrayLength, uint8_t *whichBitMask) const
181c29fa5a6Sopenharmony_ci{
182c29fa5a6Sopenharmony_ci    int32_t rc = ioctl(fd_, EVIOCGPROP(arrayLength), whichBitMask);
183c29fa5a6Sopenharmony_ci    if (rc < 0) {
184c29fa5a6Sopenharmony_ci        FI_HILOGE("Could not get %{public}s mask:%{public}s", eventName.c_str(), strerror(errno));
185c29fa5a6Sopenharmony_ci    }
186c29fa5a6Sopenharmony_ci}
187c29fa5a6Sopenharmony_ci
188c29fa5a6Sopenharmony_civoid Device::QuerySupportedEvents()
189c29fa5a6Sopenharmony_ci{
190c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
191c29fa5a6Sopenharmony_ci    GetEventMask("", 0, sizeof(evBitmask_), evBitmask_);
192c29fa5a6Sopenharmony_ci    GetEventMask("key", EV_KEY, sizeof(keyBitmask_), keyBitmask_);
193c29fa5a6Sopenharmony_ci    GetEventMask("abs", EV_ABS, sizeof(absBitmask_), absBitmask_);
194c29fa5a6Sopenharmony_ci    GetEventMask("rel", EV_REL, sizeof(relBitmask_), relBitmask_);
195c29fa5a6Sopenharmony_ci    GetPropMask("properties", sizeof(propBitmask_), propBitmask_);
196c29fa5a6Sopenharmony_ci}
197c29fa5a6Sopenharmony_ci
198c29fa5a6Sopenharmony_civoid Device::UpdateCapability()
199c29fa5a6Sopenharmony_ci{
200c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
201c29fa5a6Sopenharmony_ci    CheckPointers();
202c29fa5a6Sopenharmony_ci    CheckPencilMouse();
203c29fa5a6Sopenharmony_ci    CheckKeys();
204c29fa5a6Sopenharmony_ci}
205c29fa5a6Sopenharmony_ci
206c29fa5a6Sopenharmony_cibool Device::HasAxesOrButton(size_t start, size_t end, const uint8_t* whichBitMask) const
207c29fa5a6Sopenharmony_ci{
208c29fa5a6Sopenharmony_ci    for (size_t type = start; type < end; ++type) {
209c29fa5a6Sopenharmony_ci        if (TestBit(type, whichBitMask)) {
210c29fa5a6Sopenharmony_ci            return true;
211c29fa5a6Sopenharmony_ci        }
212c29fa5a6Sopenharmony_ci    }
213c29fa5a6Sopenharmony_ci    return false;
214c29fa5a6Sopenharmony_ci}
215c29fa5a6Sopenharmony_ci
216c29fa5a6Sopenharmony_cibool Device::HasJoystickAxesOrButtons() const
217c29fa5a6Sopenharmony_ci{
218c29fa5a6Sopenharmony_ci    if (!TestBit(BTN_JOYSTICK - 1, keyBitmask_)) {
219c29fa5a6Sopenharmony_ci        if (HasAxesOrButton(BTN_JOYSTICK, BTN_DIGI, keyBitmask_) ||
220c29fa5a6Sopenharmony_ci            // BTN_TRIGGER_HAPPY40 + 1 : loop boundary
221c29fa5a6Sopenharmony_ci            HasAxesOrButton(BTN_TRIGGER_HAPPY1, BTN_TRIGGER_HAPPY40 + 1, keyBitmask_) ||
222c29fa5a6Sopenharmony_ci            HasAxesOrButton(BTN_DPAD_UP, BTN_DPAD_RIGHT + 1, keyBitmask_)) { // BTN_DPAD_RIGHT + 1 : loop boundary
223c29fa5a6Sopenharmony_ci            return true;
224c29fa5a6Sopenharmony_ci        }
225c29fa5a6Sopenharmony_ci    }
226c29fa5a6Sopenharmony_ci    return HasAxesOrButton(ABS_RX, ABS_PRESSURE, absBitmask_);
227c29fa5a6Sopenharmony_ci}
228c29fa5a6Sopenharmony_ci
229c29fa5a6Sopenharmony_cibool Device::HasAbsCoord() const
230c29fa5a6Sopenharmony_ci{
231c29fa5a6Sopenharmony_ci    return (HasAbs(ABS_X) && HasAbs(ABS_Y));
232c29fa5a6Sopenharmony_ci}
233c29fa5a6Sopenharmony_ci
234c29fa5a6Sopenharmony_cibool Device::HasMtCoord() const
235c29fa5a6Sopenharmony_ci{
236c29fa5a6Sopenharmony_ci    return (HasAbs(ABS_MT_POSITION_X) && HasAbs(ABS_MT_POSITION_Y));
237c29fa5a6Sopenharmony_ci}
238c29fa5a6Sopenharmony_ci
239c29fa5a6Sopenharmony_cibool Device::HasRelCoord() const
240c29fa5a6Sopenharmony_ci{
241c29fa5a6Sopenharmony_ci    return (HasRel(REL_X) && HasRel(REL_Y));
242c29fa5a6Sopenharmony_ci}
243c29fa5a6Sopenharmony_ci
244c29fa5a6Sopenharmony_civoid Device::PrintCapsDevice() const
245c29fa5a6Sopenharmony_ci{
246c29fa5a6Sopenharmony_ci    const std::map<std::size_t, std::string> deviceComparisonTable {
247c29fa5a6Sopenharmony_ci        { DEVICE_CAP_KEYBOARD, "keyboard" },
248c29fa5a6Sopenharmony_ci        { DEVICE_CAP_TOUCH, "touch device" },
249c29fa5a6Sopenharmony_ci        { DEVICE_CAP_POINTER, "pointer" },
250c29fa5a6Sopenharmony_ci        { DEVICE_CAP_TABLET_TOOL, "tablet tool" },
251c29fa5a6Sopenharmony_ci        { DEVICE_CAP_TABLET_PAD, "pad" },
252c29fa5a6Sopenharmony_ci        { DEVICE_CAP_GESTURE, "gesture" },
253c29fa5a6Sopenharmony_ci        { DEVICE_CAP_SWITCH, "switch" },
254c29fa5a6Sopenharmony_ci        { DEVICE_CAP_JOYSTICK, "joystick" }
255c29fa5a6Sopenharmony_ci    };
256c29fa5a6Sopenharmony_ci    for (const auto &[cap, name]: deviceComparisonTable) {
257c29fa5a6Sopenharmony_ci        if (caps_.test(cap)) {
258c29fa5a6Sopenharmony_ci            FI_HILOGD("This is %{public}s", name.c_str());
259c29fa5a6Sopenharmony_ci        }
260c29fa5a6Sopenharmony_ci    }
261c29fa5a6Sopenharmony_ci}
262c29fa5a6Sopenharmony_ci
263c29fa5a6Sopenharmony_civoid Device::CheckPointers()
264c29fa5a6Sopenharmony_ci{
265c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
266c29fa5a6Sopenharmony_ci    if (HasAbsCoord()) {
267c29fa5a6Sopenharmony_ci        CheckAbs();
268c29fa5a6Sopenharmony_ci    } else {
269c29fa5a6Sopenharmony_ci        CheckJoystick();
270c29fa5a6Sopenharmony_ci    }
271c29fa5a6Sopenharmony_ci    if (HasMtCoord()) {
272c29fa5a6Sopenharmony_ci        CheckMt();
273c29fa5a6Sopenharmony_ci    }
274c29fa5a6Sopenharmony_ci    CheckAdditional();
275c29fa5a6Sopenharmony_ci    PrintCapsDevice();
276c29fa5a6Sopenharmony_ci}
277c29fa5a6Sopenharmony_ci
278c29fa5a6Sopenharmony_civoid Device::CheckAbs()
279c29fa5a6Sopenharmony_ci{
280c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
281c29fa5a6Sopenharmony_ci    if (HasKey(BTN_STYLUS) || HasKey(BTN_TOOL_PEN)) {
282c29fa5a6Sopenharmony_ci        caps_.set(DEVICE_CAP_TABLET_TOOL);
283c29fa5a6Sopenharmony_ci    } else if (HasKey(BTN_TOOL_FINGER) && !HasKey(BTN_TOOL_PEN) && !HasProperty(INPUT_PROP_DIRECT)) {
284c29fa5a6Sopenharmony_ci        caps_.set(DEVICE_CAP_POINTER);
285c29fa5a6Sopenharmony_ci    } else if (HasAxesOrButton(BTN_MOUSE, BTN_JOYSTICK, keyBitmask_)) {
286c29fa5a6Sopenharmony_ci        caps_.set(DEVICE_CAP_POINTER);
287c29fa5a6Sopenharmony_ci    } else if (HasKey(BTN_TOUCH) || HasProperty(INPUT_PROP_DIRECT)) {
288c29fa5a6Sopenharmony_ci        caps_.set(DEVICE_CAP_TOUCH);
289c29fa5a6Sopenharmony_ci    } else if (HasJoystickAxesOrButtons()) {
290c29fa5a6Sopenharmony_ci        caps_.set(DEVICE_CAP_JOYSTICK);
291c29fa5a6Sopenharmony_ci    }
292c29fa5a6Sopenharmony_ci}
293c29fa5a6Sopenharmony_ci
294c29fa5a6Sopenharmony_civoid Device::CheckJoystick()
295c29fa5a6Sopenharmony_ci{
296c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
297c29fa5a6Sopenharmony_ci    if (HasJoystickAxesOrButtons()) {
298c29fa5a6Sopenharmony_ci        caps_.set(DEVICE_CAP_JOYSTICK);
299c29fa5a6Sopenharmony_ci    }
300c29fa5a6Sopenharmony_ci}
301c29fa5a6Sopenharmony_ci
302c29fa5a6Sopenharmony_civoid Device::CheckMt()
303c29fa5a6Sopenharmony_ci{
304c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
305c29fa5a6Sopenharmony_ci    if (HasKey(BTN_STYLUS) || HasKey(BTN_TOOL_PEN)) {
306c29fa5a6Sopenharmony_ci        caps_.set(DEVICE_CAP_TABLET_TOOL);
307c29fa5a6Sopenharmony_ci    } else if (HasKey(BTN_TOOL_FINGER) && !HasKey(BTN_TOOL_PEN) && !HasProperty(INPUT_PROP_DIRECT)) {
308c29fa5a6Sopenharmony_ci        caps_.set(DEVICE_CAP_POINTER);
309c29fa5a6Sopenharmony_ci    } else if (HasKey(BTN_TOUCH) || HasProperty(INPUT_PROP_DIRECT)) {
310c29fa5a6Sopenharmony_ci        caps_.set(DEVICE_CAP_TOUCH);
311c29fa5a6Sopenharmony_ci    }
312c29fa5a6Sopenharmony_ci}
313c29fa5a6Sopenharmony_ci
314c29fa5a6Sopenharmony_civoid Device::CheckAdditional()
315c29fa5a6Sopenharmony_ci{
316c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
317c29fa5a6Sopenharmony_ci    if (!HasCapability(DEVICE_CAP_TABLET_TOOL) &&
318c29fa5a6Sopenharmony_ci        !HasCapability(DEVICE_CAP_POINTER) &&
319c29fa5a6Sopenharmony_ci        !HasCapability(DEVICE_CAP_JOYSTICK) &&
320c29fa5a6Sopenharmony_ci        HasAxesOrButton(BTN_MOUSE, BTN_JOYSTICK, keyBitmask_) &&
321c29fa5a6Sopenharmony_ci        (HasRelCoord() || !HasAbsCoord())) {
322c29fa5a6Sopenharmony_ci        caps_.set(DEVICE_CAP_POINTER);
323c29fa5a6Sopenharmony_ci    }
324c29fa5a6Sopenharmony_ci}
325c29fa5a6Sopenharmony_ci
326c29fa5a6Sopenharmony_civoid Device::CheckPencilMouse()
327c29fa5a6Sopenharmony_ci{
328c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
329c29fa5a6Sopenharmony_ci    if (name_ == "M-Pencil Mouse") {
330c29fa5a6Sopenharmony_ci        caps_.set(DEVICE_CAP_POINTER, 0);
331c29fa5a6Sopenharmony_ci    }
332c29fa5a6Sopenharmony_ci}
333c29fa5a6Sopenharmony_ci
334c29fa5a6Sopenharmony_civoid Device::CheckKeys()
335c29fa5a6Sopenharmony_ci{
336c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
337c29fa5a6Sopenharmony_ci    if (!TestBit(EV_KEY, evBitmask_)) {
338c29fa5a6Sopenharmony_ci        FI_HILOGD("No EV_KEY capability");
339c29fa5a6Sopenharmony_ci        return;
340c29fa5a6Sopenharmony_ci    }
341c29fa5a6Sopenharmony_ci    size_t length = sizeof(KEY_BLOCKS) / sizeof(struct Range);
342c29fa5a6Sopenharmony_ci    for (size_t block { 0U }; block < length; ++block) {
343c29fa5a6Sopenharmony_ci        for (size_t key = KEY_BLOCKS[block].start; key < KEY_BLOCKS[block].end; ++key) {
344c29fa5a6Sopenharmony_ci            if (TestBit(key, keyBitmask_)) {
345c29fa5a6Sopenharmony_ci                FI_HILOGD("Found key:%{public}zx", key);
346c29fa5a6Sopenharmony_ci                caps_.set(DEVICE_CAP_KEYBOARD);
347c29fa5a6Sopenharmony_ci                return;
348c29fa5a6Sopenharmony_ci            }
349c29fa5a6Sopenharmony_ci        }
350c29fa5a6Sopenharmony_ci    }
351c29fa5a6Sopenharmony_ci}
352c29fa5a6Sopenharmony_ci
353c29fa5a6Sopenharmony_cistd::string Device::MakeConfigFileName() const
354c29fa5a6Sopenharmony_ci{
355c29fa5a6Sopenharmony_ci    std::ostringstream ss;
356c29fa5a6Sopenharmony_ci    ss << GetVendor() << "_" << GetProduct() << "_" << GetVersion() << "_" << GetName();
357c29fa5a6Sopenharmony_ci    std::string fname { ss.str() };
358c29fa5a6Sopenharmony_ci    Utility::RemoveSpace(fname);
359c29fa5a6Sopenharmony_ci
360c29fa5a6Sopenharmony_ci    std::ostringstream sp;
361c29fa5a6Sopenharmony_ci    sp << "/vendor/etc/keymap/" << fname << ".TOML";
362c29fa5a6Sopenharmony_ci    return sp.str();
363c29fa5a6Sopenharmony_ci}
364c29fa5a6Sopenharmony_ci
365c29fa5a6Sopenharmony_ciint32_t Device::ReadConfigFile(const std::string &filePath)
366c29fa5a6Sopenharmony_ci{
367c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
368c29fa5a6Sopenharmony_ci    char realPath[PATH_MAX] = { 0 };
369c29fa5a6Sopenharmony_ci    if (realpath(filePath.c_str(), realPath) == nullptr) {
370c29fa5a6Sopenharmony_ci        FI_HILOGE("Path is error, path is %{pubilc}s", filePath.c_str());
371c29fa5a6Sopenharmony_ci        return RET_ERR;
372c29fa5a6Sopenharmony_ci    }
373c29fa5a6Sopenharmony_ci    IfStreamWrap cfgFile;
374c29fa5a6Sopenharmony_ci    cfgFile.ifStream = std::ifstream(filePath);
375c29fa5a6Sopenharmony_ci    if (!cfgFile.IsOpen()) {
376c29fa5a6Sopenharmony_ci        FI_HILOGE("Failed to open config file");
377c29fa5a6Sopenharmony_ci        return FILE_OPEN_FAIL;
378c29fa5a6Sopenharmony_ci    }
379c29fa5a6Sopenharmony_ci    std::string tmp;
380c29fa5a6Sopenharmony_ci    while (std::getline(cfgFile.ifStream, tmp)) {
381c29fa5a6Sopenharmony_ci        Utility::RemoveSpace(tmp);
382c29fa5a6Sopenharmony_ci        size_t pos = tmp.find('#');
383c29fa5a6Sopenharmony_ci        if ((pos != tmp.npos) && (pos != COMMENT_SUBSCRIPT)) {
384c29fa5a6Sopenharmony_ci            FI_HILOGE("File format is error");
385c29fa5a6Sopenharmony_ci            return RET_ERR;
386c29fa5a6Sopenharmony_ci        }
387c29fa5a6Sopenharmony_ci        if (tmp.empty() || (tmp.front() == '#')) {
388c29fa5a6Sopenharmony_ci            continue;
389c29fa5a6Sopenharmony_ci        }
390c29fa5a6Sopenharmony_ci        pos = tmp.find('=');
391c29fa5a6Sopenharmony_ci        if (tmp.size() == 0) {
392c29fa5a6Sopenharmony_ci            FI_HILOGE("Invalid size, pos will overflow");
393c29fa5a6Sopenharmony_ci            return RET_ERR;
394c29fa5a6Sopenharmony_ci        } else if ((pos == (tmp.size() - 1)) || (pos == tmp.npos)) {
395c29fa5a6Sopenharmony_ci            FI_HILOGE("Find config item error");
396c29fa5a6Sopenharmony_ci            return RET_ERR;
397c29fa5a6Sopenharmony_ci        }
398c29fa5a6Sopenharmony_ci        std::string configItem = tmp.substr(0, pos);
399c29fa5a6Sopenharmony_ci        std::string value = tmp.substr(pos + 1);
400c29fa5a6Sopenharmony_ci        if (ConfigItemSwitch(configItem, value) == RET_ERR) {
401c29fa5a6Sopenharmony_ci            FI_HILOGE("Configuration item error");
402c29fa5a6Sopenharmony_ci            return RET_ERR;
403c29fa5a6Sopenharmony_ci        }
404c29fa5a6Sopenharmony_ci    }
405c29fa5a6Sopenharmony_ci    return RET_OK;
406c29fa5a6Sopenharmony_ci}
407c29fa5a6Sopenharmony_ci
408c29fa5a6Sopenharmony_ciint32_t Device::ConfigItemSwitch(const std::string &configItem, const std::string &value)
409c29fa5a6Sopenharmony_ci{
410c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
411c29fa5a6Sopenharmony_ci    const std::string CONFIG_ITEM_KEYBOARD_TYPE { "Key.keyboard.type" };
412c29fa5a6Sopenharmony_ci    if (configItem.empty() || value.empty() || !Utility::IsInteger(value)) {
413c29fa5a6Sopenharmony_ci        FI_HILOGE("Invalid configuration encountered");
414c29fa5a6Sopenharmony_ci        return RET_ERR;
415c29fa5a6Sopenharmony_ci    }
416c29fa5a6Sopenharmony_ci    if (configItem == CONFIG_ITEM_KEYBOARD_TYPE) {
417c29fa5a6Sopenharmony_ci        keyboardType_ = static_cast<IDevice::KeyboardType>(stoi(value));
418c29fa5a6Sopenharmony_ci    }
419c29fa5a6Sopenharmony_ci    return RET_OK;
420c29fa5a6Sopenharmony_ci}
421c29fa5a6Sopenharmony_ci
422c29fa5a6Sopenharmony_ciint32_t Device::ReadTomlFile(const std::string &filePath)
423c29fa5a6Sopenharmony_ci{
424c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
425c29fa5a6Sopenharmony_ci    char temp[PATH_MAX] {};
426c29fa5a6Sopenharmony_ci    if (realpath(filePath.c_str(), temp) == nullptr) {
427c29fa5a6Sopenharmony_ci        FI_HILOGE("Not real path (\'%{public}s\'):%{public}s", filePath.c_str(), strerror(errno));
428c29fa5a6Sopenharmony_ci        return RET_ERR;
429c29fa5a6Sopenharmony_ci    }
430c29fa5a6Sopenharmony_ci    FI_HILOGD("Config file path:%{private}s", temp);
431c29fa5a6Sopenharmony_ci
432c29fa5a6Sopenharmony_ci    if (!Utility::DoesFileExist(temp)) {
433c29fa5a6Sopenharmony_ci        FI_HILOGE("File does not exist:%{public}s", temp);
434c29fa5a6Sopenharmony_ci        return RET_ERR;
435c29fa5a6Sopenharmony_ci    }
436c29fa5a6Sopenharmony_ci    if (Utility::GetFileSize(temp) > MAX_FILE_SIZE_ALLOWED) {
437c29fa5a6Sopenharmony_ci        FI_HILOGE("File size is out of range");
438c29fa5a6Sopenharmony_ci        return RET_ERR;
439c29fa5a6Sopenharmony_ci    }
440c29fa5a6Sopenharmony_ci    if (ReadConfigFile(std::string(temp)) != RET_OK) {
441c29fa5a6Sopenharmony_ci        FI_HILOGE("ReadConfigFile failed");
442c29fa5a6Sopenharmony_ci        return RET_ERR;
443c29fa5a6Sopenharmony_ci    }
444c29fa5a6Sopenharmony_ci    return RET_OK;
445c29fa5a6Sopenharmony_ci}
446c29fa5a6Sopenharmony_ci
447c29fa5a6Sopenharmony_civoid Device::JudgeKeyboardType()
448c29fa5a6Sopenharmony_ci{
449c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
450c29fa5a6Sopenharmony_ci    if (TestBit(KEY_Q, keyBitmask_)) {
451c29fa5a6Sopenharmony_ci        keyboardType_ = IDevice::KEYBOARD_TYPE_ALPHABETICKEYBOARD;
452c29fa5a6Sopenharmony_ci        FI_HILOGD("The keyboard type is standard");
453c29fa5a6Sopenharmony_ci    } else if (TestBit(KEY_HOME, keyBitmask_) && (GetBus() == BUS_BLUETOOTH)) {
454c29fa5a6Sopenharmony_ci        keyboardType_ = IDevice::KEYBOARD_TYPE_REMOTECONTROL;
455c29fa5a6Sopenharmony_ci        FI_HILOGD("The keyboard type is remote control");
456c29fa5a6Sopenharmony_ci    } else if (TestBit(KEY_KP1, keyBitmask_)) {
457c29fa5a6Sopenharmony_ci        keyboardType_ = IDevice::KEYBOARD_TYPE_DIGITALKEYBOARD;
458c29fa5a6Sopenharmony_ci        FI_HILOGD("The keyboard type is digital keyboard");
459c29fa5a6Sopenharmony_ci    } else if (TestBit(KEY_LEFTCTRL, keyBitmask_) &&
460c29fa5a6Sopenharmony_ci               TestBit(KEY_RIGHTCTRL, keyBitmask_) &&
461c29fa5a6Sopenharmony_ci               TestBit(KEY_F20, keyBitmask_)) {
462c29fa5a6Sopenharmony_ci        keyboardType_ = IDevice::KEYBOARD_TYPE_HANDWRITINGPEN;
463c29fa5a6Sopenharmony_ci        FI_HILOGD("The keyboard type is handwriting pen");
464c29fa5a6Sopenharmony_ci    } else {
465c29fa5a6Sopenharmony_ci        keyboardType_ = IDevice::KEYBOARD_TYPE_UNKNOWN;
466c29fa5a6Sopenharmony_ci        FI_HILOGD("Undefined keyboard type");
467c29fa5a6Sopenharmony_ci    }
468c29fa5a6Sopenharmony_ci}
469c29fa5a6Sopenharmony_ci
470c29fa5a6Sopenharmony_civoid Device::LoadDeviceConfig()
471c29fa5a6Sopenharmony_ci{
472c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
473c29fa5a6Sopenharmony_ci    if (ReadTomlFile(MakeConfigFileName()) != RET_OK) {
474c29fa5a6Sopenharmony_ci        FI_HILOGE("ReadTomlFile failed");
475c29fa5a6Sopenharmony_ci        keyboardType_ = IDevice::KEYBOARD_TYPE_NONE;
476c29fa5a6Sopenharmony_ci    }
477c29fa5a6Sopenharmony_ci    if (IsKeyboard()) {
478c29fa5a6Sopenharmony_ci        if ((keyboardType_ <= IDevice::KEYBOARD_TYPE_NONE) ||
479c29fa5a6Sopenharmony_ci            (keyboardType_ >= IDevice::KEYBOARD_TYPE_MAX)) {
480c29fa5a6Sopenharmony_ci            JudgeKeyboardType();
481c29fa5a6Sopenharmony_ci        }
482c29fa5a6Sopenharmony_ci    } else {
483c29fa5a6Sopenharmony_ci        keyboardType_ = IDevice::KEYBOARD_TYPE_NONE;
484c29fa5a6Sopenharmony_ci    }
485c29fa5a6Sopenharmony_ci    FI_HILOGD("keyboard type:%{public}d", keyboardType_);
486c29fa5a6Sopenharmony_ci}
487c29fa5a6Sopenharmony_ci
488c29fa5a6Sopenharmony_ci} // namespace DeviceStatus
489c29fa5a6Sopenharmony_ci} // namespace Msdp
490c29fa5a6Sopenharmony_ci} // namespace OHOS
491