mirror of
https://github.com/openharmony/distributedhardware_distributed_input.git
synced 2026-07-20 21:41:02 -04:00
Description: add dinput config
Match-id-3f13b90b873d08edcef60517478915cfa17dfb1e
This commit is contained in:
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef OHOS_DISTRIBUTED_INPUT_CONSTANTS_H
|
||||
#define OHOS_DISTRIBUTED_INPUT_CONSTANTS_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace OHOS {
|
||||
namespace DistributedHardware {
|
||||
namespace DistributedInput {
|
||||
#define INPUT_KEY_WHEN "when"
|
||||
#define INPUT_KEY_TYPE "type"
|
||||
#define INPUT_KEY_CODE "code"
|
||||
#define INPUT_KEY_VALUE "value"
|
||||
#define INPUT_KEY_DESCRIPTOR "descriptor"
|
||||
#define INPUT_KEY_PATH "path"
|
||||
|
||||
#define VIRTUAL_DEVICE_NAME "Hos Distributed Virtual Device "
|
||||
|
||||
/**
|
||||
* Status code.
|
||||
*/
|
||||
constexpr int32_t NO_ERROR = 0;
|
||||
constexpr int32_t ERROR = -1;
|
||||
|
||||
/**
|
||||
* Status code, indicates general success.
|
||||
*/
|
||||
constexpr int32_t SUCCESS = 0;
|
||||
|
||||
/**
|
||||
* Status code, indicates general failure.
|
||||
*/
|
||||
constexpr int32_t FAILURE = -60000;
|
||||
|
||||
/**
|
||||
* Status code, DISERVER general failure.
|
||||
*/
|
||||
constexpr int32_t FAILURE_DIS = -60001;
|
||||
|
||||
/**
|
||||
* Status code, hardware is resigtring.
|
||||
*/
|
||||
constexpr int32_t FAILURE_REGISTING = -60002;
|
||||
|
||||
/**
|
||||
* Status code, hardware is unresigtring.
|
||||
*/
|
||||
constexpr int32_t FAILURE_UNREGISTING = -60003;
|
||||
|
||||
/**
|
||||
* Input Type NULL.
|
||||
*/
|
||||
constexpr int32_t INPUT_TYPE_NULL = 0;
|
||||
|
||||
/**
|
||||
* Input Type MOUSE.
|
||||
*/
|
||||
constexpr int32_t INPUT_TYPE_MOUSE = 1;
|
||||
|
||||
/**
|
||||
* Input Type KEYBOARD.
|
||||
*/
|
||||
constexpr int32_t INPUT_TYPE_KEYBOARD = 2;
|
||||
|
||||
/**
|
||||
* Input Type TOUCH.
|
||||
*/
|
||||
constexpr int32_t INPUT_TYPE_TOUCH = 4;
|
||||
|
||||
/**
|
||||
* Input Type ALL.
|
||||
*/
|
||||
constexpr int32_t INPUT_TYPE_ALL = INPUT_TYPE_MOUSE | INPUT_TYPE_KEYBOARD | INPUT_TYPE_TOUCH;
|
||||
|
||||
constexpr int32_t INPUT_LOADSA_TIMEOUT_MS = 10000;
|
||||
|
||||
constexpr int32_t SESSION_WAIT_TIMEOUT_SECOND = 5;
|
||||
|
||||
enum class EHandlerMsgType {
|
||||
DINPUT_SINK_EVENT_HANDLER_MSG = 1,
|
||||
DINPUT_SOURCE_EVENT_HANDLER_MSG = 2
|
||||
};
|
||||
|
||||
struct BusinessEvent {
|
||||
std::vector<int32_t> pressedKeys;
|
||||
int32_t keyCode;
|
||||
int32_t keyAction;
|
||||
};
|
||||
|
||||
/*
|
||||
* A raw event as retrieved from the input_event.
|
||||
*/
|
||||
struct RawEvent {
|
||||
int64_t when;
|
||||
int32_t type;
|
||||
int32_t code;
|
||||
int32_t value;
|
||||
std::string descriptor;
|
||||
std::string path;
|
||||
};
|
||||
|
||||
/*
|
||||
* Input device Info retrieved from the kernel.
|
||||
*/
|
||||
struct InputDevice {
|
||||
inline InputDevice() : bus(0), vendor(0), product(0), version(0) {}
|
||||
std::string name;
|
||||
std::string location;
|
||||
std::string uniqueId;
|
||||
uint16_t bus;
|
||||
uint16_t vendor;
|
||||
uint16_t product;
|
||||
uint16_t version;
|
||||
std::string descriptor;
|
||||
uint16_t nonce;
|
||||
uint32_t classes;
|
||||
};
|
||||
|
||||
/*
|
||||
* Distributed Hardware Handle
|
||||
*/
|
||||
struct HardwareHandle {
|
||||
// equipment ID
|
||||
std::string eqId;
|
||||
|
||||
// Hardware ID
|
||||
std::string hhId;
|
||||
|
||||
// Hardware detailed information
|
||||
std::string hdInfo;
|
||||
};
|
||||
|
||||
// Synthetic raw event type codes produced when devices are added or removed.
|
||||
enum class DeviceType {
|
||||
// Sent when a device is added.
|
||||
DEVICE_ADDED = 0x10000000,
|
||||
|
||||
// Sent when a device is removed.
|
||||
DEVICE_REMOVED = 0x20000000,
|
||||
|
||||
// Sent when all added/removed devices from the most recent scan have been reported.
|
||||
// This event is always sent at least once.
|
||||
FINISHED_DEVICE_SCAN = 0x30000000,
|
||||
|
||||
FIRST_SYNTHETIC_EVENT = DEVICE_ADDED,
|
||||
};
|
||||
|
||||
/*
|
||||
* Input device connection status
|
||||
*/
|
||||
struct InputDeviceEvent {
|
||||
DeviceType type;
|
||||
InputDevice deviceInfo;
|
||||
};
|
||||
|
||||
/*
|
||||
* Input device classes.
|
||||
*/
|
||||
enum class DeviceClasses {
|
||||
/* The input device is a keyboard or has buttons. */
|
||||
INPUT_DEVICE_CLASS_KEYBOARD = 0x00000001,
|
||||
|
||||
/* The input device is an alpha-numeric keyboard (not just a dial pad). */
|
||||
INPUT_DEVICE_CLASS_ALPHAKEY = 0x00000002,
|
||||
|
||||
/* The input device is a touchscreen or a touchpad (either single-touch or multi-touch). */
|
||||
INPUT_DEVICE_CLASS_TOUCH = 0x00000004,
|
||||
|
||||
/* The input device is a cursor device such as a trackball or mouse. */
|
||||
INPUT_DEVICE_CLASS_CURSOR = 0x00000008,
|
||||
|
||||
/* The input device is a multi-touch touchscreen. */
|
||||
INPUT_DEVICE_CLASS_TOUCH_MT = 0x00000010,
|
||||
|
||||
/* The input device is a directional pad (implies keyboard, has DPAD keys). */
|
||||
INPUT_DEVICE_CLASS_DPAD = 0x00000020,
|
||||
|
||||
/* The input device is a gamepad (implies keyboard, has BUTTON keys). */
|
||||
INPUT_DEVICE_CLASS_GAMEPAD = 0x00000040,
|
||||
|
||||
/* The input device has switches. */
|
||||
INPUT_DEVICE_CLASS_SWITCH = 0x00000080,
|
||||
|
||||
/* The input device is a joystick (implies gamepad, has joystick absolute axes). */
|
||||
INPUT_DEVICE_CLASS_JOYSTICK = 0x00000100,
|
||||
|
||||
/* The input device has a vibrator (supports FF_RUMBLE). */
|
||||
INPUT_DEVICE_CLASS_VIBRATOR = 0x00000200,
|
||||
|
||||
/* The input device has a microphone. */
|
||||
INPUT_DEVICE_CLASS_MIC = 0x00000400,
|
||||
|
||||
/* The input device is an external stylus (has data we want to fuse with touch data). */
|
||||
INPUT_DEVICE_CLASS_EXTERNAL_STYLUS = 0x00000800,
|
||||
|
||||
/* The input device has a rotary encoder. */
|
||||
INPUT_DEVICE_CLASS_ROTARY_ENCODER = 0x00001000,
|
||||
|
||||
/* The input device is virtual (not a real device, not part of UI configuration). */
|
||||
INPUT_DEVICE_CLASS_VIRTUAL = 0x40000000,
|
||||
|
||||
/* The input device is external (not built-in). */
|
||||
INPUT_DEVICE_CLASS_EXTERNAL = 0x80000000,
|
||||
};
|
||||
|
||||
/**
|
||||
* Device Type definitions
|
||||
*/
|
||||
enum class DInputServerType {
|
||||
/**
|
||||
* null server
|
||||
*/
|
||||
NULL_SERVER_TYPE = 0,
|
||||
|
||||
/**
|
||||
* source server
|
||||
*/
|
||||
SOURCE_SERVER_TYPE = 1,
|
||||
|
||||
/**
|
||||
* sink server.
|
||||
*/
|
||||
SINK_SERVER_TYPE = 2,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef OHOS_DINPUT_ERRCODE_H
|
||||
#define OHOS_DINPUT_ERRCODE_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace OHOS {
|
||||
namespace DistributedHardware {
|
||||
namespace DistributedInput {
|
||||
constexpr int32_t DH_SUCCESS = 0;
|
||||
|
||||
constexpr int32_t ERR_DH_INPUT_HUB_EPOLL_INIT_FAIL = -60000;
|
||||
constexpr int32_t ERR_DH_INPUT_HUB_EPOLL_WAIT_TIMEOUT = -60001;
|
||||
constexpr int32_t ERR_DH_INPUT_HUB_OPEN_DEVICEPATH_FAIL = -60002;
|
||||
constexpr int32_t ERR_DH_INPUT_HUB_MAKE_INPUT_DEVICE_FAIL = -60003;
|
||||
constexpr int32_t ERR_DH_INPUT_HUB_MAKE_DEVICE_FAIL = -60004;
|
||||
constexpr int32_t ERR_DH_INPUT_HUB_UNREGISTER_FD_FAIL = -60005;
|
||||
constexpr int32_t ERR_DH_INPUT_HUB_GET_EVENT_FAIL = -60006;
|
||||
constexpr int32_t ERR_DH_INPUT_HUB_DEVICE_ENABLE_FAIL = -60007;
|
||||
// whilte list error code
|
||||
constexpr int32_t ERR_DH_INPUT_WHILTELIST_INIT_FAIL = -61001;
|
||||
constexpr int32_t ERR_DH_INPUT_WHILTELIST_GET_WHILTELIST_FAIL = -61002;
|
||||
// handler error code
|
||||
constexpr int32_t ERR_DH_INPUT_HANDLER_GET_DEVICE_ID_FAIL = -63000;
|
||||
// service sink error code
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SINK_COLLECTOR_INIT_FAIL = -64000;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SINK_MANAGER_INIT_FAIL = -64001;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SINK_START_SWITCH_FAIL = -64002;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SINK_GET_OPEN_SESSION_FAIL = -64003;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SINK_TRANSPORT_INIT_FAIL = -64004;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SINK_TRANSPORT_RESPPREPARE_FAIL = 64005;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SINK_TRANSPORT_RESPUNPREPARE_FAIL = -64006;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SINK_TRANSPORT_RESPSTART_FAIL = -64007;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SINK_TRANSPORT_RESPSTOP_FAIL = -64008;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SINK_TRANSPORT_SENDMESSAGE_FAIL = -64009;
|
||||
// service source error code
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_INJECT_REGISTER_FAIL = -65000;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_INJECT_UNREGISTER_FAIL = -65001;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_INJECT_PREPARE_FAIL = -65002;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_INJECT_NODE_MANAGER_IS_NULL = -65003;//
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_OPEN_DEVICE_NODE_FAIL = -65004;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_CREATE_HANDLE_FAIL = -65005;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_CLOSE_DEVICE_FAIL = -65006;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_GET_DEVICE_FAIL = -65007;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_MANAGER_INIT_FAIL = -65008;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_MANSGER_RELEASE_FAIL = -65009;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_MANAGER_REGISTER_FAIL = -65010;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_MANAGER_UNREGISTER_FAIL = -65011;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_MANAGER_REMOVE_INPUT_NODE_FAIL = -65012;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_MANAGER_DELETE_DEVICE_FAIL = -65013;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_MANAGER_PREPARE_FAIL = -65014;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_MANAGER_UNPREPARE_FAIL = -65015;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_MANAGER_START_FAIL = -65016;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_MANAGER_STOP_FAIL = -65017;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_TRANSPORT_INIT_FAIL = -65018;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_TRANSPORT_DEVICE_SESSION_STATE = -65019;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_TRANSPORT_OPEN_SESSION_FAIL = -65020;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_TRANSPORT_OPEN_SESSION_TIMEOUT = -65021;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_TRANSPORT_PREPARE_FAIL = -65022;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_TRANSPORT_UNPREPARE_FAIL = -65023;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_TRANSPORT_START_FAIL = -65024;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_TRANSPORT_STOP_FAIL = -65025;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_TRANSPORT_SENDMESSSAGE = -65026;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_MANAGERGET_CALLBACK_HANDLER_FAIL = -65027;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_MANAGER_REGISTER_MSG_IS_BAD = -65028;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_MANAGER_UNREGISTER_MSG_IS_BAD = -65029;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_MANAGER_PREPARE_MSG_IS_BAD = -65030;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_MANAGER_UNPREPARE_MSG_IS_BAD = -65031;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_MANAGER_START_MSG_IS_BAD = -65032;
|
||||
constexpr int32_t ERR_DH_INPUT_SERVER_SOURCE_MANAGER_STOP_MSG_IS_BAD = -65033;
|
||||
// handler error code
|
||||
constexpr int32_t ERR_DH_INPUT_SINK_HANDLER_INIT_SINK_SA_FAIL = -66000;
|
||||
constexpr int32_t ERR_DH_INPUT_SINK_HANDLER_INIT_SOURCE_SA_FAIL = -66001;
|
||||
// interface error code
|
||||
constexpr int32_t ERR_DH_INPUT_IPC_INVALID_DESCRIPTOR = -67000;
|
||||
constexpr int32_t ERR_DH_INPUT_CLIENT_GET_SOURCE_PROXY_FAIL = -67001;
|
||||
constexpr int32_t ERR_DH_INPUT_CLIENT_GET_SINK_PROXY_FAIL = -67002;
|
||||
constexpr int32_t ERR_DH_INPUT_CLIENT_REGISTER_FAIL = -67003;
|
||||
constexpr int32_t ERR_DH_INPUT_CLIENT_UNREGISTER_FAIL = -67004;
|
||||
constexpr int32_t ERR_DH_INPUT_CLIENT_PREPARE_FAIL = -67005;
|
||||
constexpr int32_t ERR_DH_INPUT_CLIENT_UNPREPARE_FAIL = -67006;
|
||||
constexpr int32_t ERR_DH_INPUT_CLIENT_START_FAIL = -67007;
|
||||
constexpr int32_t ERR_DH_INPUT_CLIENT_STOP_FAIL = -67008;
|
||||
constexpr int32_t ERR_DH_INPUT_SINK_PROXY_INIT_FAIL = -67009;
|
||||
constexpr int32_t ERR_DH_INPUT_SINK_PROXY_RELEASE_FAIL = -67010;
|
||||
constexpr int32_t ERR_DH_INPUT_SINK_PROXY_IS_START_INPUT_FAIL = -67011;
|
||||
constexpr int32_t ERR_DH_INPUT_SINK_STUB_ON_REMOTE_REQUEST_FAIL = -67012;
|
||||
constexpr int32_t ERR_DH_INPUT_SOURCE_PROXY_INIT_FAIL = -67013;
|
||||
constexpr int32_t ERR_DH_INPUT_SOURCE_PROXY_RELEASE_FAIL = -67014;
|
||||
constexpr int32_t ERR_DH_INPUT_SOURCE_PROXY_REGISTER_WRITE_MSG_FAIL = -67015;
|
||||
constexpr int32_t ERR_DH_INPUT_SOURCE_PROXY_REGISTER_FAIL = -67016;
|
||||
constexpr int32_t ERR_DH_INPUT_SOURCE_PROXY_UNREGISTER_WRITE_MSG_FAIL = -67017;
|
||||
constexpr int32_t ERR_DH_INPUT_SOURCE_PROXY_UNREGISTER_FAIL = -67018;
|
||||
constexpr int32_t ERR_DH_INPUT_SOURCE_PROXY_PREPARE_WRITE_MSG_FAIL = -67019;
|
||||
constexpr int32_t ERR_DH_INPUT_SOURCE_PROXY_PREPARE_FAIL = -67020;
|
||||
constexpr int32_t ERR_DH_INPUT_SOURCE_PROXY_UNPREPARE_WRITE_MSG_FAIL = -67021;
|
||||
constexpr int32_t ERR_DH_INPUT_SOURCE_PROXY_UNPREPARE_FAIL = -67022;
|
||||
constexpr int32_t ERR_DH_INPUT_SOURCE_PROXY_START_WRITE_MSG_FAIL = -67023;
|
||||
constexpr int32_t ERR_DH_INPUT_SOURCE_PROXY_START_FAIL = -67024;
|
||||
constexpr int32_t ERR_DH_INPUT_SOURCE_PROXY_STOP_WRITE_MSG_FAIL = -67025;
|
||||
constexpr int32_t ERR_DH_INPUT_SOURCE_PROXY_STOP_FAIL = -67026;
|
||||
constexpr int32_t ERR_DH_INPUT_SOURCE_PROXY_IS_START_INPUT_FAIL = -67027;
|
||||
constexpr int32_t ERR_DH_INPUT_SOURCE_STUB_ON_REMOTE_REQUEST_FAIL = -67028;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,876 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "input_hub.h"
|
||||
|
||||
#include <cinttypes>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <sstream>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <securec.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "anonymous_string.h"
|
||||
#include "distributed_hardware_log.h"
|
||||
|
||||
#include "dinput_errcode.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace DistributedHardware {
|
||||
namespace DistributedInput {
|
||||
namespace {
|
||||
static const char *DEVICE_PATH = "/dev/input";
|
||||
static const uint32_t INPUT_DEVICE_CLASS_KEYBOARD = static_cast<uint32_t>(DeviceClasses::INPUT_DEVICE_CLASS_KEYBOARD);
|
||||
static const uint32_t INPUT_DEVICE_CLASS_CURSOR = static_cast<uint32_t>(DeviceClasses::INPUT_DEVICE_CLASS_CURSOR);
|
||||
}
|
||||
|
||||
InputHub::InputHub() : needToScanDevices_(true),
|
||||
nextDeviceId_(1), pendingEventCount_(0),
|
||||
pendingEventIndex_(0), pendingINotify_(false),
|
||||
deviceChanged_(false)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
InputHub::~InputHub()
|
||||
{
|
||||
Release();
|
||||
}
|
||||
|
||||
int32_t InputHub::Initialize()
|
||||
{
|
||||
epollFd_ = epoll_create1(EPOLL_CLOEXEC);
|
||||
if (epollFd_ < 0) {
|
||||
DHLOGE("Could not create epoll instance: %s", strerror(errno));
|
||||
return ERR_DH_INPUT_HUB_EPOLL_INIT_FAIL;
|
||||
}
|
||||
|
||||
iNotifyFd_ = inotify_init();
|
||||
inputWd_ = inotify_add_watch(iNotifyFd_, DEVICE_PATH, IN_DELETE | IN_CREATE);
|
||||
if (inputWd_ < 0) {
|
||||
DHLOGE(
|
||||
"Could not register INotify for %s: %s", DEVICE_PATH, strerror(errno));
|
||||
return ERR_DH_INPUT_HUB_EPOLL_INIT_FAIL;
|
||||
}
|
||||
|
||||
struct epoll_event eventItem = {};
|
||||
eventItem.events = EPOLLIN;
|
||||
eventItem.data.fd = iNotifyFd_;
|
||||
int result = epoll_ctl(epollFd_, EPOLL_CTL_ADD, iNotifyFd_, &eventItem);
|
||||
if (result != 0) {
|
||||
DHLOGE("Could not add INotify to epoll instance. errno=%d", errno);
|
||||
return ERR_DH_INPUT_HUB_EPOLL_INIT_FAIL;
|
||||
}
|
||||
|
||||
return DH_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t InputHub::Release()
|
||||
{
|
||||
CloseAllDevicesLocked();
|
||||
|
||||
::close(epollFd_);
|
||||
::close(iNotifyFd_);
|
||||
return DH_SUCCESS;
|
||||
}
|
||||
|
||||
size_t InputHub::CollectInputEvents(RawEvent* buffer, size_t bufferSize)
|
||||
{
|
||||
size_t count;
|
||||
for (;;) {
|
||||
if (needToScanDevices_) {
|
||||
needToScanDevices_ = false;
|
||||
ScanInputDevices(DEVICE_PATH);
|
||||
}
|
||||
while (!openingDevices_.empty()) {
|
||||
std::unique_lock<std::mutex> deviceLock(visitMutex_);
|
||||
std::unique_ptr<Device> device = std::move(*openingDevices_.rbegin());
|
||||
openingDevices_.pop_back();
|
||||
DHLOGI("Reporting device opened: id=%s, name=%s\n",
|
||||
GetAnonyInt32(device->id).c_str(), device->path.c_str());
|
||||
auto [dev_it, inserted] = devices_.insert_or_assign(device->id, std::move(device));
|
||||
if (!inserted) {
|
||||
DHLOGI("Device id %s exists, replaced. \n", GetAnonyInt32(device->id).c_str());
|
||||
}
|
||||
}
|
||||
deviceChanged_ = false;
|
||||
count = GetEvents(buffer, bufferSize);
|
||||
// readNotify() will modify the list of devices so this must be done after
|
||||
// processing all other events to ensure that we read all remaining events
|
||||
// before closing the devices.
|
||||
if (pendingINotify_ && pendingEventIndex_ >= pendingEventCount_) {
|
||||
pendingINotify_ = false;
|
||||
ReadNotifyLocked();
|
||||
deviceChanged_ = true;
|
||||
}
|
||||
|
||||
// Report added or removed devices immediately.
|
||||
if (deviceChanged_) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (RefreshEpollItem() < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// All done, return the number of events we read.
|
||||
return count;
|
||||
}
|
||||
|
||||
size_t InputHub::GetEvents(RawEvent* buffer, size_t bufferSize)
|
||||
{
|
||||
RawEvent* event = buffer;
|
||||
size_t capacity = bufferSize;
|
||||
while (pendingEventIndex_ < pendingEventCount_) {
|
||||
std::unique_lock<std::mutex> my_lock(operationMutex_);
|
||||
const struct epoll_event& eventItem = mPendingEventItems[pendingEventIndex_++];
|
||||
if (eventItem.data.fd == iNotifyFd_) {
|
||||
if (eventItem.events & EPOLLIN) {
|
||||
pendingINotify_ = true;
|
||||
} else {
|
||||
DHLOGI("Received no epoll event 0x%08x.", eventItem.events);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
Device* device = GetDeviceByFd(eventItem.data.fd);
|
||||
if (!device) {
|
||||
continue;
|
||||
}
|
||||
if (eventItem.events & EPOLLIN) {
|
||||
struct input_event readBuffer[bufferSize];
|
||||
int32_t readSize = read(device->fd, readBuffer, sizeof(struct input_event) * capacity);
|
||||
size_t count = ReadInputEvent(readSize, *device);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
struct input_event& iev = readBuffer[i];
|
||||
event->when = ProcessEventTimestamp(iev);
|
||||
event->type = iev.type;
|
||||
event->code = iev.code;
|
||||
event->value = iev.value;
|
||||
event->path = device->path;
|
||||
if (event->type == EV_KEY) {
|
||||
DHLOGD("1.E2E-Test Sink collect EV_KEY, Code: %d, Value: %d, Path: %s, When: " PRId64"",
|
||||
event->code, event->value, event->path.c_str(), event->when);
|
||||
} else if (event->type == EV_REL) {
|
||||
DHLOGD("1.E2E-Test Sink collect EV_REL, Code: %d, Value: %d, Path: %s, When: " PRId64"",
|
||||
event->code, event->value, event->path.c_str(), event->when);
|
||||
} else if (event->type == EV_ABS) {
|
||||
DHLOGD("1.E2E-Test Sink collect EV_ABS, Code: %d, Value: %d, Path: %s, When: " PRId64"",
|
||||
event->code, event->value, event->path.c_str(), event->when);
|
||||
} else {
|
||||
DHLOGW("1.E2E-Test Sink collect other type!");
|
||||
}
|
||||
event->descriptor = device->identifier.descriptor;
|
||||
event += 1;
|
||||
capacity -= 1;
|
||||
}
|
||||
if (capacity == 0) {
|
||||
pendingEventIndex_ -= 1;
|
||||
break;
|
||||
}
|
||||
} else if (eventItem.events & EPOLLHUP) {
|
||||
DHLOGI("Removing device %s due to epoll hang-up event.",
|
||||
device->identifier.name.c_str());
|
||||
deviceChanged_ = true;
|
||||
CloseDeviceLocked(*device);
|
||||
}
|
||||
}
|
||||
return event - buffer;
|
||||
}
|
||||
|
||||
size_t InputHub::ReadInputEvent(int32_t readSize, Device& device)
|
||||
{
|
||||
size_t count = 0;
|
||||
if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
|
||||
// Device was removed before INotify noticed.
|
||||
DHLOGE("could not get event, removed? (fd: %d size: %d"
|
||||
" errno: %d)\n",
|
||||
device.fd, readSize, errno);
|
||||
deviceChanged_ = true;
|
||||
CloseDeviceLocked(device);
|
||||
} else if (readSize < 0) {
|
||||
if (errno != EAGAIN && errno != EINTR) {
|
||||
DHLOGW("could not get event (errno=%d)", errno);
|
||||
}
|
||||
} else if ((readSize % sizeof(struct input_event)) != 0) {
|
||||
DHLOGW("could not get event (wrong size: %d)", readSize);
|
||||
} else {
|
||||
count = size_t(readSize) / sizeof(struct input_event);
|
||||
return count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
size_t InputHub::DeviceIsExists(InputDeviceEvent* buffer, size_t bufferSize)
|
||||
{
|
||||
InputDeviceEvent* event = buffer;
|
||||
size_t capacity = bufferSize;
|
||||
// Report any devices that had last been added/removed.
|
||||
for (auto it = closingDevices_.begin(); it != closingDevices_.end();) {
|
||||
std::unique_ptr<Device> device = std::move(*it);
|
||||
DHLOGI("Reporting device closed: id=%s, name=%s\n", GetAnonyInt32(device->id).c_str(), device->path.c_str());
|
||||
event->type = DeviceType::DEVICE_REMOVED;
|
||||
event->deviceInfo = device->identifier;
|
||||
event += 1;
|
||||
it = closingDevices_.erase(it);
|
||||
if (--capacity == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (needToScanDevices_) {
|
||||
needToScanDevices_ = false;
|
||||
ScanInputDevices(DEVICE_PATH);
|
||||
}
|
||||
while (!openingDevices_.empty()) {
|
||||
std::unique_lock<std::mutex> deviceLock(visitMutex_);
|
||||
std::unique_ptr<Device> device = std::move(*openingDevices_.rbegin());
|
||||
openingDevices_.pop_back();
|
||||
DHLOGI("Reporting device opened: id=%s, name=%s\n", GetAnonyInt32(device->id).c_str(), device->path.c_str());
|
||||
event->type = DeviceType::DEVICE_ADDED;
|
||||
event->deviceInfo = device->identifier;
|
||||
event += 1;
|
||||
|
||||
auto [dev_it, inserted] = devices_.insert_or_assign(device->id, std::move(device));
|
||||
if (!inserted) {
|
||||
DHLOGI("Device id %s exists, replaced. \n", GetAnonyInt32(device->id).c_str());
|
||||
}
|
||||
if (--capacity == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return event - buffer;
|
||||
}
|
||||
|
||||
size_t InputHub::CollectInputHandler(InputDeviceEvent* buffer, size_t bufferSize)
|
||||
{
|
||||
size_t count;
|
||||
for (;;) {
|
||||
count = DeviceIsExists(buffer, bufferSize);
|
||||
deviceChanged_ = false;
|
||||
GetDeviceHandler();
|
||||
|
||||
if (pendingINotify_ && pendingEventIndex_ >= pendingEventCount_) {
|
||||
pendingINotify_ = false;
|
||||
ReadNotifyLocked();
|
||||
deviceChanged_ = true;
|
||||
}
|
||||
|
||||
// Report added or removed devices immediately.
|
||||
if (deviceChanged_) {
|
||||
continue;
|
||||
}
|
||||
if (count > 0) {
|
||||
break;
|
||||
}
|
||||
if (RefreshEpollItem() < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// All done, return the number of events we read.
|
||||
return count;
|
||||
}
|
||||
|
||||
void InputHub::GetDeviceHandler()
|
||||
{
|
||||
while (pendingEventIndex_ < pendingEventCount_) {
|
||||
std::unique_lock<std::mutex> my_lock(operationMutex_);
|
||||
const struct epoll_event& eventItem = mPendingEventItems[pendingEventIndex_++];
|
||||
if (eventItem.data.fd == iNotifyFd_) {
|
||||
if (eventItem.events & EPOLLIN) {
|
||||
pendingINotify_ = true;
|
||||
} else {
|
||||
DHLOGI(
|
||||
"Received unexpected epoll event 0x%08x for INotify.", eventItem.events);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
Device* device = GetDeviceByFdLocked(eventItem.data.fd);
|
||||
if (!device) {
|
||||
DHLOGE(
|
||||
"Received unexpected epoll event 0x%08x for unknown fd %d.",
|
||||
eventItem.events, eventItem.data.fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (eventItem.events & EPOLLHUP) {
|
||||
DHLOGI("Removing device %s due to epoll hang-up event.",
|
||||
device->identifier.name.c_str());
|
||||
deviceChanged_ = true;
|
||||
CloseDeviceLocked(*device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t InputHub::RefreshEpollItem()
|
||||
{
|
||||
pendingEventIndex_ = 0;
|
||||
int pollResult = epoll_wait(epollFd_, mPendingEventItems, EPOLL_MAX_EVENTS, 0);
|
||||
if (pollResult == 0) {
|
||||
// Timed out.
|
||||
pendingEventCount_ = 0;
|
||||
return ERR_DH_INPUT_HUB_EPOLL_WAIT_TIMEOUT;
|
||||
}
|
||||
|
||||
if (pollResult < 0) {
|
||||
// An error occurred.
|
||||
pendingEventCount_ = 0;
|
||||
|
||||
// Sleep after errors to avoid locking up the system.
|
||||
// Hopefully the error is transient.
|
||||
if (errno != EINTR) {
|
||||
DHLOGE("poll failed (errno=%d)\n", errno);
|
||||
usleep(SLEEP_TIME);
|
||||
}
|
||||
} else {
|
||||
// Some events occurred.
|
||||
pendingEventCount_ = size_t(pollResult);
|
||||
}
|
||||
return DH_SUCCESS;
|
||||
}
|
||||
|
||||
std::vector<InputDevice> InputHub::GetAllInputDevices()
|
||||
{
|
||||
std::unique_lock<std::mutex> deviceLock(visitMutex_);
|
||||
std::vector<InputDevice> vecDevice;
|
||||
for (const auto& [id, device] : devices_) {
|
||||
vecDevice.push_back(device->identifier);
|
||||
}
|
||||
return vecDevice;
|
||||
}
|
||||
|
||||
void InputHub::ScanInputDevices(const std::string& dirname)
|
||||
{
|
||||
char devname[PATH_MAX];
|
||||
char *filename;
|
||||
DIR *dir;
|
||||
struct dirent *de;
|
||||
dir = opendir(dirname.c_str());
|
||||
if (dir == nullptr) {
|
||||
DHLOGE("error opendir dev/input :%{public}s\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcpy_s(devname, PATH_MAX, dirname.c_str()) != 0) {
|
||||
DHLOGE("error strcpy_s :%{public}s\n", strerror(errno));
|
||||
}
|
||||
filename = devname + strlen(devname);
|
||||
*filename++ = '/';
|
||||
while ((de = readdir(dir))) {
|
||||
if (de->d_name[0] == '.' &&
|
||||
(de->d_name[1] == '\0' ||
|
||||
(de->d_name[1] == '.' && de->d_name[DIR_FILE_NAME_SECOND] == '\0'))) {
|
||||
continue;
|
||||
}
|
||||
if (strcpy_s(filename, sizeof(de->d_name), de->d_name) != 0) {
|
||||
DHLOGE("error strcpy_s second :%{public}s\n", strerror(errno));
|
||||
}
|
||||
DHLOGE("scan dir failed for %{public}s", filename);
|
||||
OpenInputDeviceLocked(devname);
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
int32_t InputHub::OpenInputDeviceLocked(const std::string& devicePath)
|
||||
{
|
||||
{
|
||||
std::unique_lock<std::mutex> deviceLock(visitMutex_);
|
||||
for (const auto& [deviceId, device] : devices_) {
|
||||
if (device->path == devicePath) {
|
||||
return DH_SUCCESS; // device was already registered
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> my_lock(operationMutex_);
|
||||
DHLOGI("Opening device: %s", devicePath.c_str());
|
||||
chmod(devicePath.c_str(), S_IWRITE | S_IREAD);
|
||||
int fd = open(devicePath.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
DHLOGE("could not open %s, %s\n", devicePath.c_str(), strerror(errno));
|
||||
return ERR_DH_INPUT_HUB_OPEN_DEVICEPATH_FAIL;
|
||||
}
|
||||
|
||||
InputDevice identifier;
|
||||
if (MakeInputDevice(fd, identifier) < 0) {
|
||||
return ERR_DH_INPUT_HUB_MAKE_INPUT_DEVICE_FAIL;
|
||||
}
|
||||
AssignDescriptorLocked(identifier);
|
||||
|
||||
// Allocate device. (The device object takes ownership of the fd at this point.)
|
||||
int32_t deviceId = nextDeviceId_++;
|
||||
std::unique_ptr<Device> device = std::make_unique<Device>(fd, deviceId, devicePath, identifier);
|
||||
|
||||
DHLOGI("add device %d: %s\n", deviceId, devicePath.c_str());
|
||||
DHLOGI(" bus: %04x\n"
|
||||
" vendor %04x\n"
|
||||
" product %04x\n"
|
||||
" version %04x\n",
|
||||
identifier.bus, identifier.vendor, identifier.product, identifier.version);
|
||||
DHLOGI(" name: \"%s\"\n", identifier.name.c_str());
|
||||
DHLOGI(" location: \"%s\"\n", identifier.location.c_str());
|
||||
DHLOGI(" unique id: \"%s\"\n", identifier.uniqueId.c_str());
|
||||
DHLOGI(" descriptor: \"%s\"\n", identifier.descriptor.c_str());
|
||||
|
||||
if (MakeDevice(fd, std::move(device)) < 0) {
|
||||
return ERR_DH_INPUT_HUB_MAKE_DEVICE_FAIL;
|
||||
}
|
||||
|
||||
return DH_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t InputHub::MakeInputDevice(int fd, InputDevice& identifier)
|
||||
{
|
||||
char buffer[80] = {};
|
||||
// Get device name.
|
||||
if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
|
||||
DHLOGE(
|
||||
"Could not get device name for %s", strerror(errno));
|
||||
} else {
|
||||
buffer[sizeof(buffer) - 1] = '\0';
|
||||
identifier.name = buffer;
|
||||
}
|
||||
|
||||
// If the device is already a virtual device, don't monitor it.
|
||||
if (identifier.name.find(VIRTUAL_DEVICE_NAME) != std::string::npos) {
|
||||
return ERR_DH_INPUT_HUB_MAKE_INPUT_DEVICE_FAIL;
|
||||
}
|
||||
// Get device driver version.
|
||||
int driverVersion;
|
||||
if (ioctl(fd, EVIOCGVERSION, &driverVersion)) {
|
||||
DHLOGE("could not get driver version for %s\n", strerror(errno));
|
||||
close(fd);
|
||||
return ERR_DH_INPUT_HUB_MAKE_INPUT_DEVICE_FAIL;
|
||||
}
|
||||
// Get device identifier.
|
||||
struct input_id inputId;
|
||||
if (ioctl(fd, EVIOCGID, &inputId)) {
|
||||
DHLOGE("could not get device input id for %s\n", strerror(errno));
|
||||
close(fd);
|
||||
return ERR_DH_INPUT_HUB_MAKE_INPUT_DEVICE_FAIL;
|
||||
}
|
||||
identifier.bus = inputId.bustype;
|
||||
identifier.product = inputId.product;
|
||||
identifier.vendor = inputId.vendor;
|
||||
identifier.version = inputId.version;
|
||||
// Get device physical location.
|
||||
if (ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
|
||||
DHLOGE("could not get location for %s\n", strerror(errno));
|
||||
} else {
|
||||
buffer[sizeof(buffer) - 1] = '\0';
|
||||
identifier.location = buffer;
|
||||
}
|
||||
// Get device unique id.
|
||||
if (ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
|
||||
DHLOGE("could not get idstring for %s\n", strerror(errno));
|
||||
} else {
|
||||
buffer[sizeof(buffer) - 1] = '\0';
|
||||
identifier.uniqueId = buffer;
|
||||
}
|
||||
|
||||
return DH_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t InputHub::MakeDevice(int fd, std::unique_ptr<Device> device)
|
||||
{
|
||||
// Figure out the kinds of events the device reports.
|
||||
ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device->keyBitmask)), device->keyBitmask);
|
||||
ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(device->absBitmask)), device->absBitmask);
|
||||
ioctl(fd, EVIOCGBIT(EV_REL, sizeof(device->relBitmask)), device->relBitmask);
|
||||
|
||||
// See if this is a keyboard.
|
||||
bool haveKeyboardKeys = ContainsNonZeroByte(device->keyBitmask, 0, SizeofBitArray(BTN_MISC));
|
||||
if (haveKeyboardKeys) {
|
||||
device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
|
||||
}
|
||||
|
||||
// See if this is a cursor device such as a trackball or mouse.
|
||||
if (TestBit(BTN_MOUSE, device->keyBitmask)
|
||||
&& TestBit(REL_X, device->relBitmask)
|
||||
&& TestBit(REL_Y, device->relBitmask)) {
|
||||
device->classes |= INPUT_DEVICE_CLASS_CURSOR;
|
||||
}
|
||||
|
||||
// If the device isn't recognized as something we handle, don't monitor it.
|
||||
if (device->classes == 0) {
|
||||
DHLOGI("Dropping device: name='%s'", device->identifier.name.c_str());
|
||||
return ERR_DH_INPUT_HUB_MAKE_DEVICE_FAIL;
|
||||
}
|
||||
|
||||
if (RegisterDeviceForEpollLocked(*device) != DH_SUCCESS) {
|
||||
return ERR_DH_INPUT_HUB_MAKE_DEVICE_FAIL;
|
||||
}
|
||||
|
||||
DHLOGI("New device: fd=%d, name='%s', classes=0x%x,",
|
||||
fd, device->identifier.name.c_str(), device->classes);
|
||||
device->identifier.classes = device->classes;
|
||||
AddDeviceLocked(std::move(device));
|
||||
return DH_SUCCESS;
|
||||
}
|
||||
|
||||
void InputHub::AssignDescriptorLocked(InputDevice& identifier)
|
||||
{
|
||||
identifier.nonce = 0;
|
||||
std::string rawDescriptor = GenerateDescriptor(identifier);
|
||||
if (identifier.uniqueId.empty()) {
|
||||
// If it didn't have a unique id check for conflicts and enforce
|
||||
// uniqueness if necessary.
|
||||
while (GetDeviceByDescriptorLocked(identifier.descriptor) != nullptr) {
|
||||
identifier.nonce++;
|
||||
rawDescriptor = GenerateDescriptor(identifier);
|
||||
}
|
||||
}
|
||||
DHLOGI(
|
||||
"Created descriptor: raw=%s, cooked=%s", rawDescriptor.c_str(),
|
||||
identifier.descriptor.c_str());
|
||||
}
|
||||
|
||||
std::string InputHub::StringPrintf(const char* format, ...) const
|
||||
{
|
||||
static const int kSpaceLength = 1024;
|
||||
char space[kSpaceLength];
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
std::string result;
|
||||
int ret = vsnprintf_s(space, sizeof(space), sizeof(space) - 1, format, ap);
|
||||
if (ret >= DH_SUCCESS && ret < sizeof(space)) {
|
||||
result = space;
|
||||
} else {
|
||||
return "the buffer is overflow!";
|
||||
}
|
||||
va_end(ap);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string InputHub::Sha256(const std::string& in) const
|
||||
{
|
||||
SHA256_CTX ctx;
|
||||
SHA256_Init(&ctx);
|
||||
SHA256_Update(&ctx, reinterpret_cast<const u_char*>(in.c_str()), in.size());
|
||||
u_char digest[SHA_DIGEST_LENGTH];
|
||||
SHA256_Final(digest, &ctx);
|
||||
|
||||
std::string out;
|
||||
for (size_t i = 0; i < SHA_DIGEST_LENGTH; i++) {
|
||||
out += StringPrintf("%02x", digest[i]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string InputHub::GenerateDescriptor(InputDevice& identifier) const
|
||||
{
|
||||
std::string rawDescriptor;
|
||||
rawDescriptor += StringPrintf(":%04x:%04x:", identifier.vendor,
|
||||
identifier.product);
|
||||
// add handling for USB devices to not uniqueify kbs that show up twice
|
||||
if (!identifier.uniqueId.empty()) {
|
||||
rawDescriptor += "uniqueId:";
|
||||
rawDescriptor += identifier.uniqueId;
|
||||
} else if (identifier.nonce != 0) {
|
||||
rawDescriptor += StringPrintf("nonce:%04x", identifier.nonce);
|
||||
}
|
||||
|
||||
if (identifier.vendor == 0 && identifier.product == 0) {
|
||||
// If we don't know the vendor and product id, then the device is probably
|
||||
// built-in so we need to rely on other information to uniquely identify
|
||||
// the input device. Usually we try to avoid relying on the device name or
|
||||
// location but for built-in input device, they are unlikely to ever change.
|
||||
if (!identifier.name.empty()) {
|
||||
rawDescriptor += "name:";
|
||||
rawDescriptor += identifier.name;
|
||||
} else if (!identifier.location.empty()) {
|
||||
rawDescriptor += "location:";
|
||||
rawDescriptor += identifier.location;
|
||||
}
|
||||
}
|
||||
identifier.descriptor = Sha256(rawDescriptor);
|
||||
return rawDescriptor;
|
||||
}
|
||||
|
||||
int32_t InputHub::RegisterDeviceForEpollLocked(const Device& device)
|
||||
{
|
||||
int32_t result = RegisterFdForEpoll(device.fd);
|
||||
if (result != DH_SUCCESS) {
|
||||
DHLOGE("Could not add input device fd to epoll for device %d", device.id);
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t InputHub::RegisterFdForEpoll(int fd)
|
||||
{
|
||||
struct epoll_event eventItem = {};
|
||||
eventItem.events = EPOLLIN | EPOLLWAKEUP;
|
||||
eventItem.data.fd = fd;
|
||||
if (epoll_ctl(epollFd_, EPOLL_CTL_ADD, fd, &eventItem)) {
|
||||
DHLOGE(
|
||||
"Could not add fd to epoll instance: %s", strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
return DH_SUCCESS;
|
||||
}
|
||||
|
||||
void InputHub::AddDeviceLocked(std::unique_ptr<Device> device)
|
||||
{
|
||||
std::unique_lock<std::mutex> deviceLock(visitMutex_);
|
||||
openingDevices_.push_back(std::move(device));
|
||||
}
|
||||
|
||||
void InputHub::CloseDeviceLocked(Device& device)
|
||||
{
|
||||
DHLOGI(
|
||||
"Removed device: path=%s name=%s id=%s fd=%d classes=0x%x",
|
||||
device.path.c_str(), device.identifier.name.c_str(), GetAnonyInt32(device.id).c_str(),
|
||||
device.fd, device.classes);
|
||||
|
||||
UnregisterDeviceFromEpollLocked(device);
|
||||
device.Close();
|
||||
std::unique_lock<std::mutex> deviceLock(visitMutex_);
|
||||
closingDevices_.push_back(std::move(devices_[device.id]));
|
||||
devices_.erase(device.id);
|
||||
}
|
||||
|
||||
int32_t InputHub::UnregisterDeviceFromEpollLocked(const Device& device) const
|
||||
{
|
||||
if (device.HasValidFd()) {
|
||||
int32_t result = UnregisterFdFromEpoll(device.fd);
|
||||
if (result != DH_SUCCESS) {
|
||||
DHLOGE(
|
||||
"Could not remove input device fd from epoll for device %s", GetAnonyInt32(device.id).c_str());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return DH_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t InputHub::UnregisterFdFromEpoll(int fd) const
|
||||
{
|
||||
if (epoll_ctl(epollFd_, EPOLL_CTL_DEL, fd, nullptr)) {
|
||||
DHLOGE(
|
||||
"Could not remove fd from epoll instance: %s", strerror(errno));
|
||||
return ERR_DH_INPUT_HUB_UNREGISTER_FD_FAIL;
|
||||
}
|
||||
return DH_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t InputHub::ReadNotifyLocked()
|
||||
{
|
||||
int res;
|
||||
char event_buf[512];
|
||||
int event_size;
|
||||
int event_pos = 0;
|
||||
struct inotify_event *event;
|
||||
|
||||
DHLOGI("readNotify nfd: %d\n", iNotifyFd_);
|
||||
res = read(iNotifyFd_, event_buf, sizeof(event_buf));
|
||||
if (res < (int)sizeof(*event)) {
|
||||
if (errno == EINTR)
|
||||
return DH_SUCCESS;
|
||||
DHLOGE("could not get event, %s\n", strerror(errno));
|
||||
return ERR_DH_INPUT_HUB_GET_EVENT_FAIL;
|
||||
}
|
||||
|
||||
while (res >= (int) sizeof(*event)) {
|
||||
event = (struct inotify_event *)(event_buf + event_pos);
|
||||
JudgeDeviceOpenOrClose(*event);
|
||||
event_size = sizeof(*event) + event->len;
|
||||
res -= event_size;
|
||||
event_pos += event_size;
|
||||
}
|
||||
return DH_SUCCESS;
|
||||
}
|
||||
|
||||
void InputHub::JudgeDeviceOpenOrClose(const inotify_event& event)
|
||||
{
|
||||
if (event.len) {
|
||||
if (event.wd == inputWd_) {
|
||||
std::string filename = std::string(DEVICE_PATH) + "/" + event.name;
|
||||
if (event.mask & IN_CREATE) {
|
||||
OpenInputDeviceLocked(filename);
|
||||
} else {
|
||||
DHLOGI(
|
||||
"Removing device '%s' due to inotify event\n", filename.c_str());
|
||||
CloseDeviceByPathLocked(filename);
|
||||
}
|
||||
} else {
|
||||
DHLOGI("Unexpected inotify event, wd = %i", event.wd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InputHub::CloseDeviceByPathLocked(const std::string& devicePath)
|
||||
{
|
||||
Device* device = GetDeviceByPathLocked(devicePath);
|
||||
if (device) {
|
||||
CloseDeviceLocked(*device);
|
||||
return;
|
||||
}
|
||||
DHLOGI(
|
||||
"Remove device: %s not found, device may already have been removed.", devicePath.c_str());
|
||||
}
|
||||
|
||||
void InputHub::CloseAllDevicesLocked()
|
||||
{
|
||||
while (!devices_.empty()) {
|
||||
CloseDeviceLocked(*(devices_.begin()->second));
|
||||
}
|
||||
}
|
||||
|
||||
InputHub::Device* InputHub::GetDeviceByDescriptorLocked(const std::string& descriptor)
|
||||
{
|
||||
std::unique_lock<std::mutex> deviceLock(visitMutex_);
|
||||
for (const auto& [id, device] : devices_) {
|
||||
if (descriptor == device->identifier.descriptor) {
|
||||
return device.get();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
InputHub::Device* InputHub::GetDeviceByPathLocked(const std::string& devicePath)
|
||||
{
|
||||
std::unique_lock<std::mutex> deviceLock(visitMutex_);
|
||||
for (const auto& [id, device] : devices_) {
|
||||
if (device->path == devicePath) {
|
||||
return device.get();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
InputHub::Device* InputHub::GetDeviceByFdLocked(int fd)
|
||||
{
|
||||
std::unique_lock<std::mutex> deviceLock(visitMutex_);
|
||||
for (const auto& [id, device] : devices_) {
|
||||
if (device->fd == fd) {
|
||||
return device.get();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
InputHub::Device* InputHub::GetDeviceByFd(int fd)
|
||||
{
|
||||
std::unique_lock<std::mutex> deviceLock(visitMutex_);
|
||||
for (const auto& [id, device] : devices_) {
|
||||
if (device->fd == fd) {
|
||||
if (GetIsSupportInputTypes(device->classes)) {
|
||||
return device.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool InputHub::ContainsNonZeroByte(const uint8_t* array, uint32_t startIndex, uint32_t endIndex)
|
||||
{
|
||||
const uint8_t* end = array + endIndex;
|
||||
array += startIndex;
|
||||
while (array != end) {
|
||||
if (*(array++) != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t InputHub::ProcessEventTimestamp(const input_event& event)
|
||||
{
|
||||
const int64_t inputEventTime = event.input_event_sec * 1000000000LL + event.input_event_usec * 1000LL;
|
||||
return inputEventTime;
|
||||
}
|
||||
|
||||
bool InputHub::TestBit(uint32_t bit, const uint8_t* array)
|
||||
{
|
||||
constexpr int units = 8;
|
||||
return (array)[(bit) / units] & (1 << ((bit) % units));
|
||||
}
|
||||
|
||||
uint32_t InputHub::SizeofBitArray(uint32_t bit)
|
||||
{
|
||||
constexpr int round = 7;
|
||||
constexpr int divisor = 8;
|
||||
return ((bit) + round) / divisor;
|
||||
}
|
||||
|
||||
bool InputHub::GetIsSupportInputTypes(uint32_t classes)
|
||||
{
|
||||
return classes & input_types_;
|
||||
}
|
||||
void InputHub::SetSupportInputType(const uint32_t& inputTypes)
|
||||
{
|
||||
input_types_ = inputTypes;
|
||||
DHLOGI("SetSupportInputType: inputTypes=0x%x,", input_types_);
|
||||
}
|
||||
|
||||
InputHub::Device::Device(int fd, int32_t id, const std::string& path,
|
||||
const InputDevice& identifier) : next(nullptr), fd(fd), id(id), path(path), identifier(identifier),
|
||||
classes(0), enabled(true), isVirtual(fd < 0) {
|
||||
memset_s(keyBitmask, sizeof(keyBitmask), 0, sizeof(keyBitmask));
|
||||
memset_s(absBitmask, sizeof(absBitmask), 0, sizeof(absBitmask));
|
||||
memset_s(relBitmask, sizeof(relBitmask), 0, sizeof(relBitmask));
|
||||
}
|
||||
|
||||
InputHub::Device::~Device()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void InputHub::Device::Close()
|
||||
{
|
||||
if (fd >= 0) {
|
||||
::close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t InputHub::Device::Enable()
|
||||
{
|
||||
chmod(path.c_str(), S_IWRITE | S_IREAD);
|
||||
fd = open(path.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
DHLOGE("could not open %s, %s\n", path.c_str(), strerror(errno));
|
||||
return ERR_DH_INPUT_HUB_DEVICE_ENABLE_FAIL;
|
||||
}
|
||||
enabled = true;
|
||||
return DH_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t InputHub::Device::Disable()
|
||||
{
|
||||
Close();
|
||||
enabled = false;
|
||||
return DH_SUCCESS;
|
||||
}
|
||||
|
||||
bool InputHub::Device::HasValidFd() const
|
||||
{
|
||||
return !isVirtual && enabled;
|
||||
}
|
||||
} // namespace DistributedInput
|
||||
} // namespace DistributedHardware
|
||||
} // namespace OHOS
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef INPUT_HUB_H
|
||||
#define INPUT_HUB_H
|
||||
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/inotify.h>
|
||||
|
||||
#include <linux/input.h>
|
||||
|
||||
#include "constants_dinput.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace DistributedHardware {
|
||||
namespace DistributedInput {
|
||||
class InputHub {
|
||||
public:
|
||||
InputHub();
|
||||
~InputHub();
|
||||
size_t CollectInputEvents(RawEvent* buffer, size_t bufferSize);
|
||||
size_t CollectInputHandler(InputDeviceEvent* buffer, size_t bufferSize);
|
||||
size_t DeviceIsExists(InputDeviceEvent* event, size_t capacity);
|
||||
std::vector<InputDevice> GetAllInputDevices();
|
||||
void SetSupportInputType(const uint32_t& inputType);
|
||||
private:
|
||||
struct Device {
|
||||
Device* next;
|
||||
int fd; // may be -1 if device is closed
|
||||
const int32_t id;
|
||||
const std::string path;
|
||||
InputDevice identifier;
|
||||
uint32_t classes;
|
||||
uint8_t keyBitmask[(KEY_MAX + 1) / 8];
|
||||
uint8_t absBitmask[(ABS_MAX + 1) / 8];
|
||||
uint8_t relBitmask[(REL_MAX + 1) / 8];
|
||||
|
||||
Device(int fd, int32_t id, const std::string& path,
|
||||
const InputDevice& identifier);
|
||||
~Device();
|
||||
void Close();
|
||||
bool enabled; // initially true
|
||||
int32_t Enable();
|
||||
int32_t Disable();
|
||||
bool HasValidFd() const;
|
||||
const bool isVirtual; // set if fd < 0 is passed to constructor
|
||||
};
|
||||
|
||||
int32_t Initialize();
|
||||
int32_t Release();
|
||||
|
||||
size_t GetEvents(RawEvent* buffer, size_t bufferSize);
|
||||
size_t ReadInputEvent(int32_t readSize, Device& device);
|
||||
void GetDeviceHandler();
|
||||
int32_t RefreshEpollItem();
|
||||
|
||||
void ScanInputDevices(const std::string& dirname);
|
||||
int32_t OpenInputDeviceLocked(const std::string& devicePath);
|
||||
int32_t MakeInputDevice(int fd, InputDevice& identifier);
|
||||
int32_t MakeDevice(int fd, std::unique_ptr<Device> device);
|
||||
void AssignDescriptorLocked(InputDevice& identifier);
|
||||
std::string GenerateDescriptor(InputDevice& identifier) const;
|
||||
std::string StringPrintf(const char* format, ...) const;
|
||||
std::string Sha256(const std::string& in) const;
|
||||
|
||||
int32_t RegisterFdForEpoll(int fd);
|
||||
int32_t RegisterDeviceForEpollLocked(const Device& device);
|
||||
void AddDeviceLocked(std::unique_ptr<Device> device);
|
||||
void CloseDeviceLocked(Device& device);
|
||||
int32_t UnregisterDeviceFromEpollLocked(const Device& device) const;
|
||||
int32_t UnregisterFdFromEpoll(int fd) const;
|
||||
int32_t ReadNotifyLocked();
|
||||
void CloseDeviceByPathLocked(const std::string& devicePath);
|
||||
void CloseAllDevicesLocked();
|
||||
void JudgeDeviceOpenOrClose(const inotify_event& event);
|
||||
Device* GetDeviceByDescriptorLocked(const std::string& descriptor);
|
||||
Device* GetDeviceByPathLocked(const std::string& devicePath);
|
||||
Device* GetDeviceByFdLocked(int fd);
|
||||
Device* GetDeviceByFd(int fd);
|
||||
|
||||
bool ContainsNonZeroByte(const uint8_t* array, uint32_t startIndex, uint32_t endIndex);
|
||||
int64_t ProcessEventTimestamp(const input_event& event);
|
||||
/* this macro is used to tell if "bit" is set in "array"
|
||||
* it selects a byte from the array, and does a boolean AND
|
||||
* operation with a byte that only has the relevant bit set.
|
||||
* eg. to check for the 12th bit, we do (array[1] & 1<<4)
|
||||
*/
|
||||
bool TestBit(uint32_t bit, const uint8_t* array);
|
||||
/* this macro computes the number of bytes needed to represent a bit array of the specified size */
|
||||
uint32_t SizeofBitArray(uint32_t bit);
|
||||
bool GetIsSupportInputTypes(uint32_t classes);
|
||||
|
||||
int epollFd_;
|
||||
int iNotifyFd_;
|
||||
int inputWd_;
|
||||
|
||||
std::vector<std::unique_ptr<Device>> openingDevices_;
|
||||
std::vector<std::unique_ptr<Device>> closingDevices_;
|
||||
std::unordered_map<int32_t, std::unique_ptr<Device>> devices_;
|
||||
bool needToScanDevices_;
|
||||
std::string deviceId_;
|
||||
int32_t nextDeviceId_;
|
||||
|
||||
// Maximum number of signalled FDs to handle at a time.
|
||||
static const int EPOLL_MAX_EVENTS = 16;
|
||||
static const int SLEEP_TIME = 100000;
|
||||
// The array of pending epoll events and the index of the next event to be handled.
|
||||
struct epoll_event mPendingEventItems[EPOLL_MAX_EVENTS];
|
||||
size_t pendingEventCount_;
|
||||
size_t pendingEventIndex_;
|
||||
bool pendingINotify_;
|
||||
std::mutex operationMutex_;
|
||||
std::mutex visitMutex_;
|
||||
bool deviceChanged_;
|
||||
uint32_t input_types_;
|
||||
|
||||
static const int DIR_FILE_NAME_SECOND = 2;
|
||||
static const int MOVE_POSITION_SIXTEEN = 16;
|
||||
static const int DRIVER_VERSION_MOVE = 8;
|
||||
static const uint16_t DRIVER_VERSION_MAX = 0xff;
|
||||
};
|
||||
} // namespace DistributedInput
|
||||
} // namespace DistributedHardware
|
||||
} // namespace OHOS
|
||||
|
||||
#endif // INPUT_HUB_H
|
||||
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "white_list_util.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "anonymous_string.h"
|
||||
#include "distributed_hardware_log.h"
|
||||
|
||||
#include "dinput_errcode.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace DistributedHardware {
|
||||
namespace DistributedInput {
|
||||
namespace {
|
||||
const char *g_filepath = "/system/profile/dinput_business_event_whitelist.cfg";
|
||||
const char *g_splitSymbol1 = ",";
|
||||
const char *g_splitSymbol2 = "|";
|
||||
}
|
||||
|
||||
WhiteListUtil::WhiteListUtil()
|
||||
{
|
||||
}
|
||||
|
||||
WhiteListUtil::~WhiteListUtil()
|
||||
{
|
||||
}
|
||||
|
||||
WhiteListUtil &WhiteListUtil::GetInstance(void)
|
||||
{
|
||||
static WhiteListUtil instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
int32_t WhiteListUtil::Init(const std::string &deviceId)
|
||||
{
|
||||
DHLOGI("start, deviceId=%s", GetAnonyString(deviceId).c_str());
|
||||
ClearWhiteList();
|
||||
|
||||
if (deviceId.empty()) {
|
||||
// device id error
|
||||
DHLOGE("%s error, deviceId empty", __func__);
|
||||
return ERR_DH_INPUT_WHILTELIST_INIT_FAIL;
|
||||
}
|
||||
|
||||
std::ifstream inFile(g_filepath, std::ios::in | std::ios::binary);
|
||||
if (!inFile.is_open()) {
|
||||
// file open error
|
||||
DHLOGE("%s error, file open fail path=%s", __func__, g_filepath);
|
||||
return ERR_DH_INPUT_WHILTELIST_INIT_FAIL;
|
||||
}
|
||||
|
||||
TYPE_KEY_CODE_VEC vecKeyCode;
|
||||
TYPE_COMBINATION_KEY_VEC vecCombinationKey;
|
||||
TYPE_WHITE_LIST_VEC vecWhiteList;
|
||||
|
||||
std::string line;
|
||||
while (getline(inFile, line)) {
|
||||
DHLOGI("%s called success, line=%s", __func__, line.c_str());
|
||||
|
||||
vecKeyCode.clear();
|
||||
vecCombinationKey.clear();
|
||||
|
||||
std::size_t pos1 = line.find(g_splitSymbol1);
|
||||
while (std::string::npos != pos1) {
|
||||
std::string column = line.substr(0, pos1);
|
||||
line = line.substr(pos1 + 1, line.size());
|
||||
pos1 = line.find(g_splitSymbol1);
|
||||
vecKeyCode.clear();
|
||||
ReadLineDataStepOne(column, vecKeyCode, vecCombinationKey);
|
||||
}
|
||||
|
||||
if (!line.empty()) {
|
||||
int32_t keyCode = std::stoi(line);
|
||||
if (keyCode) {
|
||||
vecKeyCode.push_back(keyCode);
|
||||
}
|
||||
|
||||
if (!vecKeyCode.empty()) {
|
||||
vecCombinationKey.push_back(vecKeyCode);
|
||||
vecKeyCode.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (!vecCombinationKey.empty()) {
|
||||
vecWhiteList.push_back(vecCombinationKey);
|
||||
vecCombinationKey.clear();
|
||||
}
|
||||
}
|
||||
|
||||
inFile.close();
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
mapDeviceWhiteList_[deviceId] = vecWhiteList;
|
||||
|
||||
DHLOGI("success, deviceId=%s", GetAnonyString(deviceId).c_str());
|
||||
return DH_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t WhiteListUtil::UnInit(void)
|
||||
{
|
||||
DHLOGI("%s called", __func__);
|
||||
ClearWhiteList();
|
||||
return DH_SUCCESS;
|
||||
}
|
||||
|
||||
void WhiteListUtil::ReadLineDataStepOne(std::string &column, TYPE_KEY_CODE_VEC &vecKeyCode,
|
||||
TYPE_COMBINATION_KEY_VEC &vecCombinationKey) const
|
||||
{
|
||||
std::size_t pos2 = column.find(g_splitSymbol2);
|
||||
while (std::string::npos != pos2) {
|
||||
std::string single = column.substr(0, pos2);
|
||||
column = column.substr(pos2 + 1, column.size());
|
||||
pos2 = column.find(g_splitSymbol2);
|
||||
|
||||
if (!single.empty()) {
|
||||
int32_t keyCode = std::stoi(single);
|
||||
if (keyCode) {
|
||||
vecKeyCode.push_back(keyCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!column.empty()) {
|
||||
int32_t keyCode = std::stoi(column);
|
||||
if (keyCode) {
|
||||
vecKeyCode.push_back(keyCode);
|
||||
}
|
||||
}
|
||||
|
||||
if (!vecKeyCode.empty()) {
|
||||
vecCombinationKey.push_back(vecKeyCode);
|
||||
vecKeyCode.clear();
|
||||
}
|
||||
}
|
||||
|
||||
int32_t WhiteListUtil::SyncWhiteList(const std::string &deviceId, const TYPE_WHITE_LIST_VEC &vecWhiteList)
|
||||
{
|
||||
DHLOGI("deviceId=%s", GetAnonyString(deviceId).c_str());
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
mapDeviceWhiteList_[deviceId] = vecWhiteList;
|
||||
return DH_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t WhiteListUtil::ClearWhiteList(const std::string &deviceId)
|
||||
{
|
||||
DHLOGI("deviceId=%s", GetAnonyString(deviceId).c_str());
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
mapDeviceWhiteList_.erase(deviceId);
|
||||
return DH_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t WhiteListUtil::ClearWhiteList(void)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
TYPE_DEVICE_WHITE_LIST_MAP().swap(mapDeviceWhiteList_);
|
||||
return DH_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t WhiteListUtil::GetWhiteList(const std::string &deviceId, TYPE_WHITE_LIST_VEC &vecWhiteList)
|
||||
{
|
||||
DHLOGI("start, deviceId=%s", GetAnonyString(deviceId).c_str());
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
TYPE_DEVICE_WHITE_LIST_MAP::iterator iter = mapDeviceWhiteList_.find(deviceId);
|
||||
if (iter != mapDeviceWhiteList_.end()) {
|
||||
vecWhiteList = iter->second;
|
||||
DHLOGI("GetWhiteList success, deviceId=%s", GetAnonyString(deviceId).c_str());
|
||||
return DH_SUCCESS;
|
||||
}
|
||||
|
||||
DHLOGI("GetWhiteList fail, deviceId=%s", GetAnonyString(deviceId).c_str());
|
||||
return ERR_DH_INPUT_WHILTELIST_GET_WHILTELIST_FAIL;
|
||||
}
|
||||
|
||||
bool WhiteListUtil::CheckSubVecData(const TYPE_COMBINATION_KEY_VEC::iterator &iter2,
|
||||
const TYPE_KEY_CODE_VEC::iterator &iter3) const
|
||||
{
|
||||
bool bIsMatching = false;
|
||||
for (TYPE_KEY_CODE_VEC::iterator iter4 = iter2->begin(); iter4 != iter2->end(); ++iter4) {
|
||||
if (*iter4 == *iter3) {
|
||||
bIsMatching = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return bIsMatching;
|
||||
}
|
||||
|
||||
bool WhiteListUtil::IsNeedFilterOut(const std::string &deviceId, const BusinessEvent &event)
|
||||
{
|
||||
DHLOGI("start, deviceId=%s", GetAnonyString(deviceId).c_str());
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (mapDeviceWhiteList_.empty()) {
|
||||
DHLOGE("%s called, whilte list is empty!", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
TYPE_DEVICE_WHITE_LIST_MAP::iterator iter = mapDeviceWhiteList_.find(deviceId);
|
||||
if (iter == mapDeviceWhiteList_.end()) {
|
||||
DHLOGE("%s called, not find by deviceId!", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
TYPE_KEY_CODE_VEC vecKeyCode = event.pressedKeys;
|
||||
vecKeyCode.push_back(event.keyCode);
|
||||
vecKeyCode.push_back(event.keyAction);
|
||||
if (vecKeyCode.empty()) {
|
||||
DHLOGE("%s called, vecKeyCode is empty!", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bIsMatching = false;
|
||||
TYPE_WHITE_LIST_VEC vecWhiteList = iter->second;
|
||||
for (TYPE_WHITE_LIST_VEC::iterator iter1 = vecWhiteList.begin(); iter1 != vecWhiteList.end(); ++iter1) {
|
||||
if (vecKeyCode.size() != iter1->size()) {
|
||||
DHLOGI(
|
||||
"%s called, vecKeyCodeSize=%d, iter1Size=%d",
|
||||
__func__, vecKeyCode.size(), iter1->size());
|
||||
continue;
|
||||
}
|
||||
|
||||
TYPE_COMBINATION_KEY_VEC::iterator iter2 = iter1->begin();
|
||||
TYPE_KEY_CODE_VEC::iterator iter3 = vecKeyCode.begin();
|
||||
for (; iter2 != iter1->end() && iter3 != vecKeyCode.end(); ++iter2, ++iter3) {
|
||||
bIsMatching = false;
|
||||
bIsMatching = CheckSubVecData(iter2, iter3);
|
||||
if (!bIsMatching) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bIsMatching) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DHLOGI("%s called, bIsMatching=%d", __func__, bIsMatching);
|
||||
return bIsMatching;
|
||||
}
|
||||
} // namespace DistributedInput
|
||||
} // namespace DistributedHardware
|
||||
} // namespace OHOS
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WHITE_LIST_UTIL_H
|
||||
#define WHITE_LIST_UTIL_H
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include "constants_dinput.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace DistributedHardware {
|
||||
namespace DistributedInput {
|
||||
using TYPE_KEY_CODE_VEC = std::vector<int32_t>;
|
||||
using TYPE_COMBINATION_KEY_VEC = std::vector<TYPE_KEY_CODE_VEC>;
|
||||
using TYPE_WHITE_LIST_VEC = std::vector<TYPE_COMBINATION_KEY_VEC>;
|
||||
using TYPE_DEVICE_WHITE_LIST_MAP = std::map<std::string, TYPE_WHITE_LIST_VEC>;
|
||||
class WhiteListUtil {
|
||||
public:
|
||||
static WhiteListUtil &GetInstance(void);
|
||||
int32_t Init(const std::string &deviceId);
|
||||
int32_t UnInit(void);
|
||||
int32_t SyncWhiteList(const std::string &deviceId, const TYPE_WHITE_LIST_VEC &vecWhiteList);
|
||||
int32_t ClearWhiteList(const std::string &deviceId);
|
||||
int32_t ClearWhiteList(void);
|
||||
int32_t GetWhiteList(const std::string &deviceId, TYPE_WHITE_LIST_VEC &vecWhiteList);
|
||||
bool IsNeedFilterOut(const std::string &deviceId, const BusinessEvent &event);
|
||||
private:
|
||||
WhiteListUtil();
|
||||
~WhiteListUtil();
|
||||
WhiteListUtil(const WhiteListUtil &other) = delete;
|
||||
const WhiteListUtil &operator=(const WhiteListUtil &other) = delete;
|
||||
void ReadLineDataStepOne(std::string &column, TYPE_KEY_CODE_VEC &vecKeyCode,
|
||||
TYPE_COMBINATION_KEY_VEC &vecCombinationKey) const;
|
||||
bool CheckSubVecData(const TYPE_COMBINATION_KEY_VEC::iterator &iter2,
|
||||
const TYPE_KEY_CODE_VEC::iterator &iter3) const;
|
||||
private:
|
||||
TYPE_DEVICE_WHITE_LIST_MAP mapDeviceWhiteList_;
|
||||
std::mutex mutex_;
|
||||
};
|
||||
} // namespace DistributedInput
|
||||
} // namespace DistributedHardware
|
||||
} // namespace OHOS
|
||||
|
||||
#endif // WHITE_LIST_UTIL_H
|
||||
Reference in New Issue
Block a user