12d4d9a4dSopenharmony_ci/*
22d4d9a4dSopenharmony_ci * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
32d4d9a4dSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
42d4d9a4dSopenharmony_ci * you may not use this file except in compliance with the License.
52d4d9a4dSopenharmony_ci * You may obtain a copy of the License at
62d4d9a4dSopenharmony_ci *
72d4d9a4dSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
82d4d9a4dSopenharmony_ci *
92d4d9a4dSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
102d4d9a4dSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
112d4d9a4dSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122d4d9a4dSopenharmony_ci * See the License for the specific language governing permissions and
132d4d9a4dSopenharmony_ci * limitations under the License.
142d4d9a4dSopenharmony_ci */
152d4d9a4dSopenharmony_ci
162d4d9a4dSopenharmony_ci#ifndef INPUT_HUB_H
172d4d9a4dSopenharmony_ci#define INPUT_HUB_H
182d4d9a4dSopenharmony_ci
192d4d9a4dSopenharmony_ci#include <atomic>
202d4d9a4dSopenharmony_ci#include <mutex>
212d4d9a4dSopenharmony_ci#include <map>
222d4d9a4dSopenharmony_ci#include <memory>
232d4d9a4dSopenharmony_ci#include <set>
242d4d9a4dSopenharmony_ci#include <unordered_map>
252d4d9a4dSopenharmony_ci
262d4d9a4dSopenharmony_ci#include <libevdev/libevdev.h>
272d4d9a4dSopenharmony_ci#include <linux/input.h>
282d4d9a4dSopenharmony_ci#include <sys/epoll.h>
292d4d9a4dSopenharmony_ci#include <sys/inotify.h>
302d4d9a4dSopenharmony_ci
312d4d9a4dSopenharmony_ci#include "constants_dinput.h"
322d4d9a4dSopenharmony_ci
332d4d9a4dSopenharmony_cinamespace OHOS {
342d4d9a4dSopenharmony_cinamespace DistributedHardware {
352d4d9a4dSopenharmony_cinamespace DistributedInput {
362d4d9a4dSopenharmony_cistruct AffectDhIds {
372d4d9a4dSopenharmony_ci    std::vector<std::string> sharingDhIds;
382d4d9a4dSopenharmony_ci    std::vector<std::string> noSharingDhIds;
392d4d9a4dSopenharmony_ci};
402d4d9a4dSopenharmony_ci
412d4d9a4dSopenharmony_ciinline constexpr size_t BITS_PER_UINT8 { 8 };
422d4d9a4dSopenharmony_ciinline constexpr size_t NBYTES(size_t nbits)
432d4d9a4dSopenharmony_ci{
442d4d9a4dSopenharmony_ci    return (nbits + BITS_PER_UINT8 - 1) / BITS_PER_UINT8;
452d4d9a4dSopenharmony_ci}
462d4d9a4dSopenharmony_ci
472d4d9a4dSopenharmony_ciclass InputHub {
482d4d9a4dSopenharmony_cipublic:
492d4d9a4dSopenharmony_ci    struct Device  {
502d4d9a4dSopenharmony_ci        Device* next;
512d4d9a4dSopenharmony_ci        int fd; // may be -1 if device is closed
522d4d9a4dSopenharmony_ci        const std::string path;
532d4d9a4dSopenharmony_ci        InputDevice identifier;
542d4d9a4dSopenharmony_ci        uint32_t classes;
552d4d9a4dSopenharmony_ci        uint8_t evBitmask[NBYTES(EV_MAX)] {};
562d4d9a4dSopenharmony_ci        uint8_t keyBitmask[NBYTES(KEY_MAX)] {};
572d4d9a4dSopenharmony_ci        uint8_t absBitmask[NBYTES(ABS_MAX)] {};
582d4d9a4dSopenharmony_ci        uint8_t relBitmask[NBYTES(REL_MAX)] {};
592d4d9a4dSopenharmony_ci
602d4d9a4dSopenharmony_ci        Device(int fd, const std::string &path);
612d4d9a4dSopenharmony_ci        ~Device();
622d4d9a4dSopenharmony_ci        void Close();
632d4d9a4dSopenharmony_ci        bool enabled; // initially true
642d4d9a4dSopenharmony_ci        bool isShare;
652d4d9a4dSopenharmony_ci        int32_t Enable();
662d4d9a4dSopenharmony_ci        int32_t Disable();
672d4d9a4dSopenharmony_ci        bool HasValidFd() const;
682d4d9a4dSopenharmony_ci        const bool isVirtual; // set if fd < 0 is passed to constructor
692d4d9a4dSopenharmony_ci    };
702d4d9a4dSopenharmony_ci
712d4d9a4dSopenharmony_ci    struct AbsInfo {
722d4d9a4dSopenharmony_ci        uint32_t absX;
732d4d9a4dSopenharmony_ci        uint32_t absY;
742d4d9a4dSopenharmony_ci        int32_t absXIndex;
752d4d9a4dSopenharmony_ci        int32_t absYIndex;
762d4d9a4dSopenharmony_ci    };
772d4d9a4dSopenharmony_ci
782d4d9a4dSopenharmony_ci    explicit InputHub(bool isPluginMonitor);
792d4d9a4dSopenharmony_ci    ~InputHub();
802d4d9a4dSopenharmony_ci    size_t StartCollectInputEvents(RawEvent *buffer, size_t bufferSize);
812d4d9a4dSopenharmony_ci    size_t StartCollectInputHandler(InputDeviceEvent *buffer, size_t bufferSize);
822d4d9a4dSopenharmony_ci    void StopCollectInputEvents();
832d4d9a4dSopenharmony_ci    void StopCollectInputHandler();
842d4d9a4dSopenharmony_ci    size_t DeviceIsExists(InputDeviceEvent *buffer, size_t bufferSize);
852d4d9a4dSopenharmony_ci    std::vector<InputDevice> GetAllInputDevices();
862d4d9a4dSopenharmony_ci    // return efftive dhids
872d4d9a4dSopenharmony_ci    AffectDhIds SetSupportInputType(bool enabled, const uint32_t &inputTypes);
882d4d9a4dSopenharmony_ci    // return efftive dhids
892d4d9a4dSopenharmony_ci    AffectDhIds SetSharingDevices(bool enabled, std::vector<std::string> dhIds);
902d4d9a4dSopenharmony_ci    std::vector<std::string> GetSharingDevices();
912d4d9a4dSopenharmony_ci    void GetDevicesInfoByType(const uint32_t inputTypes, std::map<int32_t, std::string> &datas);
922d4d9a4dSopenharmony_ci    void GetDevicesInfoByDhId(std::vector<std::string> dhidsVec, std::map<int32_t, std::string> &datas);
932d4d9a4dSopenharmony_ci    void GetSharedMousePathByDhId(const std::vector<std::string> &dhIds, std::string &sharedMousePath,
942d4d9a4dSopenharmony_ci        std::string &sharedMouseDhId);
952d4d9a4dSopenharmony_ci    void GetSharedKeyboardPathsByDhIds(const std::vector<std::string> &dhIds,
962d4d9a4dSopenharmony_ci        std::vector<std::string> &sharedKeyboardPaths, std::vector<std::string> &sharedKeyboardDhIds);
972d4d9a4dSopenharmony_ci    bool IsAllDevicesStoped();
982d4d9a4dSopenharmony_ci    void ScanInputDevices(const std::string &dirName);
992d4d9a4dSopenharmony_ci
1002d4d9a4dSopenharmony_ci    void RecordDeviceStates();
1012d4d9a4dSopenharmony_ci    void CheckTargetDevicesState(std::vector<Device*> targetDevices);
1022d4d9a4dSopenharmony_ci    bool IsLengthExceeds(const unsigned long *keyState, const unsigned long len, int keyIndex);
1032d4d9a4dSopenharmony_ci    void CheckTargetKeyState(const InputHub::Device *dev, const unsigned long *keyState, const unsigned long len);
1042d4d9a4dSopenharmony_ci    void SavePressedKeyState(const Device *dev, int32_t keyCode);
1052d4d9a4dSopenharmony_ci    void ClearDeviceStates();
1062d4d9a4dSopenharmony_ci    void ClearSkipDevicePaths();
1072d4d9a4dSopenharmony_ci    /*
1082d4d9a4dSopenharmony_ci     * Scan the input device node and save info.
1092d4d9a4dSopenharmony_ci     */
1102d4d9a4dSopenharmony_ci    void ScanAndRecordInputDevices();
1112d4d9a4dSopenharmony_ci
1122d4d9a4dSopenharmony_ciprivate:
1132d4d9a4dSopenharmony_ci    int32_t Initialize();
1142d4d9a4dSopenharmony_ci    int32_t Release();
1152d4d9a4dSopenharmony_ci
1162d4d9a4dSopenharmony_ci    size_t GetEvents(RawEvent *buffer, size_t bufferSize);
1172d4d9a4dSopenharmony_ci    size_t ReadInputEvent(int32_t readSize, Device &device);
1182d4d9a4dSopenharmony_ci    void GetDeviceHandler();
1192d4d9a4dSopenharmony_ci    int32_t RefreshEpollItem(bool isSleep);
1202d4d9a4dSopenharmony_ci
1212d4d9a4dSopenharmony_ci    int32_t OpenInputDeviceLocked(const std::string &devicePath);
1222d4d9a4dSopenharmony_ci    int32_t QueryInputDeviceInfo(int fd, std::unique_ptr<Device> &device);
1232d4d9a4dSopenharmony_ci    void QueryEventInfo(int fd, std::unique_ptr<Device> &device);
1242d4d9a4dSopenharmony_ci    struct libevdev* GetLibEvDev(int fd);
1252d4d9a4dSopenharmony_ci    void GetEventTypes(struct libevdev *dev, InputDevice &identifier);
1262d4d9a4dSopenharmony_ci    int32_t GetEventKeys(struct libevdev *dev, InputDevice &identifier);
1272d4d9a4dSopenharmony_ci    int32_t GetABSInfo(struct libevdev *dev, InputDevice &identifier);
1282d4d9a4dSopenharmony_ci    int32_t GetRELTypes(struct libevdev *dev, InputDevice &identifier);
1292d4d9a4dSopenharmony_ci    void GetProperties(struct libevdev *dev, InputDevice &identifier);
1302d4d9a4dSopenharmony_ci
1312d4d9a4dSopenharmony_ci    void GetMSCBits(int fd, std::unique_ptr<Device> &device);
1322d4d9a4dSopenharmony_ci    void GetLEDBits(int fd, std::unique_ptr<Device> &device);
1332d4d9a4dSopenharmony_ci    void GetSwitchBits(int fd, std::unique_ptr<Device> &device);
1342d4d9a4dSopenharmony_ci    void GetRepeatBits(int fd, std::unique_ptr<Device> &device);
1352d4d9a4dSopenharmony_ci
1362d4d9a4dSopenharmony_ci    void GetEventMask(int fd, const std::string &eventName, uint32_t type,
1372d4d9a4dSopenharmony_ci        std::size_t arrayLength, uint8_t *whichBitMask) const;
1382d4d9a4dSopenharmony_ci
1392d4d9a4dSopenharmony_ci    int32_t MakeDevice(int fd, std::unique_ptr<Device> device);
1402d4d9a4dSopenharmony_ci    void GenerateDescriptor(InputDevice &identifier) const;
1412d4d9a4dSopenharmony_ci    std::string StringPrintf(const char *format, ...) const;
1422d4d9a4dSopenharmony_ci
1432d4d9a4dSopenharmony_ci    int32_t RegisterFdForEpoll(int fd);
1442d4d9a4dSopenharmony_ci    int32_t RegisterDeviceForEpollLocked(const Device &device);
1452d4d9a4dSopenharmony_ci    void AddDeviceLocked(std::unique_ptr<Device> device);
1462d4d9a4dSopenharmony_ci    void CloseDeviceLocked(Device &device);
1472d4d9a4dSopenharmony_ci    void CloseDeviceForAllLocked(Device &device);
1482d4d9a4dSopenharmony_ci    int32_t UnregisterDeviceFromEpollLocked(const Device &device) const;
1492d4d9a4dSopenharmony_ci    int32_t UnregisterFdFromEpoll(int fd) const;
1502d4d9a4dSopenharmony_ci    int32_t ReadNotifyLocked();
1512d4d9a4dSopenharmony_ci    void CloseDeviceByPathLocked(const std::string &devicePath);
1522d4d9a4dSopenharmony_ci    void CloseAllDevicesLocked();
1532d4d9a4dSopenharmony_ci    void JudgeDeviceOpenOrClose(const inotify_event &event);
1542d4d9a4dSopenharmony_ci    Device* GetDeviceByPathLocked(const std::string &devicePath);
1552d4d9a4dSopenharmony_ci    Device* GetDeviceByFdLocked(int fd);
1562d4d9a4dSopenharmony_ci    Device* GetSupportDeviceByFd(int fd);
1572d4d9a4dSopenharmony_ci    bool IsDeviceRegistered(const std::string &devicePath);
1582d4d9a4dSopenharmony_ci
1592d4d9a4dSopenharmony_ci    bool ContainsNonZeroByte(const uint8_t *array, uint32_t startIndex, uint32_t endIndex);
1602d4d9a4dSopenharmony_ci    int64_t ProcessEventTimestamp(const input_event &event);
1612d4d9a4dSopenharmony_ci    bool IsCuror(Device *device);
1622d4d9a4dSopenharmony_ci    bool IsTouchPad(const InputDevice &inputDevice);
1632d4d9a4dSopenharmony_ci    bool IsTouchPad(Device *device);
1642d4d9a4dSopenharmony_ci
1652d4d9a4dSopenharmony_ci    /*
1662d4d9a4dSopenharmony_ci     * this macro is used to tell if "bit" is set in "array"
1672d4d9a4dSopenharmony_ci     * it selects a byte from the array, and does a boolean AND
1682d4d9a4dSopenharmony_ci     * operation with a byte that only has the relevant bit set.
1692d4d9a4dSopenharmony_ci     * eg. to check for the 12th bit, we do (array[1] & 1<<4)
1702d4d9a4dSopenharmony_ci     */
1712d4d9a4dSopenharmony_ci    bool TestBit(uint32_t bit, const uint8_t *array);
1722d4d9a4dSopenharmony_ci    /* this macro computes the number of bytes needed to represent a bit array of the specified size */
1732d4d9a4dSopenharmony_ci    uint32_t SizeofBitArray(uint32_t bit);
1742d4d9a4dSopenharmony_ci    void RecordEventLog(const RawEvent *event);
1752d4d9a4dSopenharmony_ci    // Record Event log that will change the key state.
1762d4d9a4dSopenharmony_ci    void RecordChangeEventLog(const RawEvent &event);
1772d4d9a4dSopenharmony_ci    void RecordDeviceLog(const std::string &devicePath, const InputDevice &identifier);
1782d4d9a4dSopenharmony_ci    void HandleTouchScreenEvent(struct input_event readBuffer[], const size_t count, std::vector<bool> &needFilted);
1792d4d9a4dSopenharmony_ci    int32_t QueryLocalTouchScreenInfo(int fd, std::unique_ptr<Device> &device);
1802d4d9a4dSopenharmony_ci    bool CheckTouchPointRegion(struct input_event readBuffer[], const AbsInfo &absInfo);
1812d4d9a4dSopenharmony_ci    size_t CollectEvent(RawEvent *buffer, size_t &capacity, Device *device, struct input_event readBuffer[],
1822d4d9a4dSopenharmony_ci        const size_t count);
1832d4d9a4dSopenharmony_ci    /*
1842d4d9a4dSopenharmony_ci     * isEnable: true for sharing dhid, false for no sharing dhid
1852d4d9a4dSopenharmony_ci     */
1862d4d9a4dSopenharmony_ci    void SaveAffectDhId(bool isEnable, const std::string &dhId, AffectDhIds &affDhIds);
1872d4d9a4dSopenharmony_ci    /*
1882d4d9a4dSopenharmony_ci     * Record Mouse/KeyBoard/TouchPad state such as key down.
1892d4d9a4dSopenharmony_ci     */
1902d4d9a4dSopenharmony_ci    void RecordDeviceChangeStates(Device *device, struct input_event readBuffer[], const size_t count);
1912d4d9a4dSopenharmony_ci    void MatchAndDealEvent(Device *device, const RawEvent &event);
1922d4d9a4dSopenharmony_ci    void DealTouchPadEvent(const RawEvent &event);
1932d4d9a4dSopenharmony_ci    void DealNormalKeyEvent(Device *device, const RawEvent &event);
1942d4d9a4dSopenharmony_ci
1952d4d9a4dSopenharmony_ci    /*
1962d4d9a4dSopenharmony_ci     * Check is this node has been scaned for collecting info.
1972d4d9a4dSopenharmony_ci     * Return: True for scaned and cached. False for not scaned.
1982d4d9a4dSopenharmony_ci     */
1992d4d9a4dSopenharmony_ci    bool IsInputNodeNoNeedScan(const std::string &path);
2002d4d9a4dSopenharmony_ci
2012d4d9a4dSopenharmony_ci    /*
2022d4d9a4dSopenharmony_ci     * Some input device should simulate state for pass through, such as Mouse, KeyBoard, TouchPad, etc.
2032d4d9a4dSopenharmony_ci     * Before we prepare the pass through, we need check and get the key states of these devices.
2042d4d9a4dSopenharmony_ci     */
2052d4d9a4dSopenharmony_ci    std::vector<Device*> CollectTargetDevices();
2062d4d9a4dSopenharmony_ci
2072d4d9a4dSopenharmony_ci    void RecordSkipDevicePath(std::string path);
2082d4d9a4dSopenharmony_ci    bool IsSkipDevicePath(const std::string &path);
2092d4d9a4dSopenharmony_ci    void IncreaseLogTimes(const std::string& dhId);
2102d4d9a4dSopenharmony_ci    bool IsNeedPrintLog(const std::string& dhId) const;
2112d4d9a4dSopenharmony_ci
2122d4d9a4dSopenharmony_ciprivate:
2132d4d9a4dSopenharmony_ci    int epollFd_;
2142d4d9a4dSopenharmony_ci    int iNotifyFd_;
2152d4d9a4dSopenharmony_ci    int inputWd_;
2162d4d9a4dSopenharmony_ci    /*
2172d4d9a4dSopenharmony_ci     * true: for just monitor device plugin/unplugin;
2182d4d9a4dSopenharmony_ci     * false: for read device events.
2192d4d9a4dSopenharmony_ci     */
2202d4d9a4dSopenharmony_ci    bool isPluginMonitor_;
2212d4d9a4dSopenharmony_ci
2222d4d9a4dSopenharmony_ci    std::vector<std::unique_ptr<Device>> openingDevices_;
2232d4d9a4dSopenharmony_ci    std::vector<std::unique_ptr<Device>> closingDevices_;
2242d4d9a4dSopenharmony_ci    std::unordered_map<std::string, std::unique_ptr<Device>> devices_;
2252d4d9a4dSopenharmony_ci    std::mutex devicesMutex_;
2262d4d9a4dSopenharmony_ci
2272d4d9a4dSopenharmony_ci    std::mutex skipDevicePathsMutex_;
2282d4d9a4dSopenharmony_ci    std::set<std::string> skipDevicePaths_;
2292d4d9a4dSopenharmony_ci
2302d4d9a4dSopenharmony_ci    std::atomic<bool> needToScanDevices_;
2312d4d9a4dSopenharmony_ci    std::string touchDescriptor;
2322d4d9a4dSopenharmony_ci
2332d4d9a4dSopenharmony_ci    // The array of pending epoll events and the index of the next event to be handled.
2342d4d9a4dSopenharmony_ci    struct epoll_event mPendingEventItems[EPOLL_MAX_EVENTS];
2352d4d9a4dSopenharmony_ci    std::atomic<int32_t> pendingEventCount_;
2362d4d9a4dSopenharmony_ci    std::atomic<int32_t> pendingEventIndex_;
2372d4d9a4dSopenharmony_ci    std::atomic<bool> pendingINotify_;
2382d4d9a4dSopenharmony_ci    std::mutex operationMutex_;
2392d4d9a4dSopenharmony_ci
2402d4d9a4dSopenharmony_ci    std::atomic<bool> deviceChanged_;
2412d4d9a4dSopenharmony_ci    std::atomic<uint32_t> inputTypes_;
2422d4d9a4dSopenharmony_ci    std::atomic<bool> isStartCollectEvent_;
2432d4d9a4dSopenharmony_ci    std::atomic<bool> isStartCollectHandler_;
2442d4d9a4dSopenharmony_ci    std::unordered_map<std::string, bool> sharedDHIds_;
2452d4d9a4dSopenharmony_ci    std::unordered_map<std::string, int32_t> logTimesMap_;
2462d4d9a4dSopenharmony_ci};
2472d4d9a4dSopenharmony_ci} // namespace DistributedInput
2482d4d9a4dSopenharmony_ci} // namespace DistributedHardware
2492d4d9a4dSopenharmony_ci} // namespace OHOS
2502d4d9a4dSopenharmony_ci
2512d4d9a4dSopenharmony_ci#endif // INPUT_HUB_H
252