Home | History | Annotate | Download | only in evdev
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ANDROID_INPUT_HUB_H_
     18 #define ANDROID_INPUT_HUB_H_
     19 
     20 #include <memory>
     21 #include <string>
     22 #include <unordered_map>
     23 
     24 #include <utils/String8.h>
     25 #include <utils/Timers.h>
     26 
     27 namespace android {
     28 
     29 /**
     30  * InputEvent represents an event from the kernel. The fields largely mirror
     31  * those found in linux/input.h.
     32  */
     33 struct InputEvent {
     34     nsecs_t when;
     35 
     36     int32_t type;
     37     int32_t code;
     38     int32_t value;
     39 };
     40 
     41 /** Describes an absolute axis. */
     42 struct AbsoluteAxisInfo {
     43     int32_t minValue = 0;   // minimum value
     44     int32_t maxValue = 0;   // maximum value
     45     int32_t flat = 0;       // center flat position, e.g. flat == 8 means center is between -8 and 8
     46     int32_t fuzz = 0;       // error tolerance, e.g. fuzz == 4 means value is +/- 4 due to noise
     47     int32_t resolution = 0; // resolution in units per mm or radians per mm
     48 };
     49 
     50 /**
     51  * An InputDeviceNode represents a device node in the Linux system. It can be
     52  * used to interact with the device, setting and getting property values.
     53  *
     54  * An InputDeviceNode should only be used on the same thread that is polling for
     55  * input events.
     56  */
     57 class InputDeviceNode {
     58 public:
     59     /** Get the Linux device path for the node. */
     60     virtual const std::string& getPath() const = 0;
     61 
     62     /** Get the name of the device returned by the driver. */
     63     virtual const std::string& getName() const = 0;
     64     /** Get the location of the device returned by the driver. */
     65     virtual const std::string& getLocation() const = 0;
     66     /** Get the unique id of the device returned by the driver. */
     67     virtual const std::string& getUniqueId() const = 0;
     68 
     69     /** Get the bus type of the device returned by the driver. */
     70     virtual uint16_t getBusType() const = 0;
     71     /** Get the vendor id of the device returned by the driver. */
     72     virtual uint16_t getVendorId() const = 0;
     73     /** Get the product id of the device returned by the driver. */
     74     virtual uint16_t getProductId() const = 0;
     75     /** Get the version of the device driver. */
     76     virtual uint16_t getVersion() const = 0;
     77 
     78     /** Returns true if the device has the key. */
     79     virtual bool hasKey(int32_t key) const = 0;
     80     /** Returns true if the device has a key in the range [startKey, endKey). */
     81     virtual bool hasKeyInRange(int32_t startKey, int32_t endKey) const = 0;
     82     /** Returns true if the device has the relative axis. */
     83     virtual bool hasRelativeAxis(int32_t axis) const = 0;
     84     /** Returns true if the device has the absolute axis. */
     85     virtual bool hasAbsoluteAxis(int32_t axis) const = 0;
     86     /** Returns true if the device has the switch. */
     87     virtual bool hasSwitch(int32_t sw) const = 0;
     88     /** Returns true if the device has the force feedback method. */
     89     virtual bool hasForceFeedback(int32_t ff) const = 0;
     90     /** Returns true if the device has the input property. */
     91     virtual bool hasInputProperty(int property) const = 0;
     92 
     93     /** Returns the state of the key. */
     94     virtual int32_t getKeyState(int32_t key) const = 0;
     95     /** Returns the state of the switch. */
     96     virtual int32_t getSwitchState(int32_t sw) const = 0;
     97     /** Returns information about the absolute axis. */
     98     virtual const AbsoluteAxisInfo* getAbsoluteAxisInfo(int32_t axis) const = 0;
     99     /** Returns the value of the absolute axis. */
    100     virtual status_t getAbsoluteAxisValue(int32_t axis, int32_t* outValue) const = 0;
    101 
    102     /** Vibrate the device for duration ns. */
    103     virtual void vibrate(nsecs_t duration) = 0;
    104     /** Stop vibration on the device. */
    105     virtual void cancelVibrate() = 0;
    106 
    107     /** Disable key repeat for the device in the driver. */
    108     virtual void disableDriverKeyRepeat() = 0;
    109 
    110 protected:
    111     InputDeviceNode() = default;
    112     virtual ~InputDeviceNode() = default;
    113 };
    114 
    115 /** Callback interface for receiving input events, including device changes. */
    116 class InputCallbackInterface {
    117 public:
    118     virtual void onInputEvent(const std::shared_ptr<InputDeviceNode>& node, InputEvent& event,
    119             nsecs_t event_time) = 0;
    120     virtual void onDeviceAdded(const std::shared_ptr<InputDeviceNode>& node) = 0;
    121     virtual void onDeviceRemoved(const std::shared_ptr<InputDeviceNode>& node) = 0;
    122 
    123 protected:
    124     InputCallbackInterface() = default;
    125     virtual ~InputCallbackInterface() = default;
    126 };
    127 
    128 /**
    129  * InputHubInterface is responsible for monitoring a set of device paths and
    130  * executing callbacks when events occur. Before calling poll(), you should set
    131  * the device and input callbacks, and register your device path(s).
    132  */
    133 class InputHubInterface {
    134 public:
    135     virtual status_t registerDevicePath(const std::string& path) = 0;
    136     virtual status_t unregisterDevicePath(const std::string& path) = 0;
    137 
    138     virtual status_t poll() = 0;
    139     virtual status_t wake() = 0;
    140 
    141     virtual void dump(String8& dump) = 0;
    142 
    143 protected:
    144     InputHubInterface() = default;
    145     virtual ~InputHubInterface() = default;
    146 };
    147 
    148 /**
    149  * An implementation of InputHubInterface that uses epoll to wait for events.
    150  *
    151  * This class is not threadsafe. Any functions called on the InputHub should be
    152  * called on the same thread that is used to call poll(). The only exception is
    153  * wake(), which may be used to return from poll() before an input or device
    154  * event occurs.
    155  */
    156 class InputHub : public InputHubInterface {
    157 public:
    158     explicit InputHub(const std::shared_ptr<InputCallbackInterface>& cb);
    159     virtual ~InputHub() override;
    160 
    161     virtual status_t registerDevicePath(const std::string& path) override;
    162     virtual status_t unregisterDevicePath(const std::string& path) override;
    163 
    164     virtual status_t poll() override;
    165     virtual status_t wake() override;
    166 
    167     virtual void dump(String8& dump) override;
    168 
    169 private:
    170     status_t readNotify();
    171     status_t scanDir(const std::string& path);
    172     std::shared_ptr<InputDeviceNode> openNode(const std::string& path);
    173     status_t closeNode(const InputDeviceNode* node);
    174     status_t closeNodeByFd(int fd);
    175     std::shared_ptr<InputDeviceNode> findNodeByPath(const std::string& path);
    176 
    177     enum class WakeMechanism {
    178         /**
    179          * The kernel supports the EPOLLWAKEUP flag for epoll_ctl.
    180          *
    181          * When using this mechanism, epoll_wait will internally acquire a wake
    182          * lock whenever one of the FDs it is monitoring becomes ready. The wake
    183          * lock is held automatically by the kernel until the next call to
    184          * epoll_wait.
    185          *
    186          * This mechanism only exists in Linux kernel 3.5+.
    187          */
    188         EPOLL_WAKEUP,
    189         /**
    190          * The kernel evdev driver supports the EVIOCSSUSPENDBLOCK ioctl.
    191          *
    192          * When using this mechanism, the InputHub asks evdev to acquire and
    193          * hold a wake lock whenever its buffer is non-empty. We must take care
    194          * to acquire our own userspace wake lock before draining the buffer to
    195          * prevent actually going back into suspend before we have fully
    196          * processed all of the events.
    197          *
    198          * This mechanism only exists in older Android Linux kernels.
    199          */
    200         LEGACY_EVDEV_SUSPENDBLOCK_IOCTL,
    201         /**
    202          * The kernel doesn't seem to support any special wake mechanism.
    203          *
    204          * We explicitly acquire and release wake locks when processing input
    205          * events.
    206          */
    207         LEGACY_EVDEV_EXPLICIT_WAKE_LOCKS,
    208     };
    209     WakeMechanism mWakeupMechanism = WakeMechanism::LEGACY_EVDEV_EXPLICIT_WAKE_LOCKS;
    210     bool manageWakeLocks() const;
    211     bool mNeedToCheckSuspendBlockIoctl = true;
    212 
    213     int mEpollFd;
    214     int mINotifyFd;
    215     int mWakeEventFd;
    216 
    217     // Callback for input events
    218     std::shared_ptr<InputCallbackInterface> mInputCallback;
    219 
    220     // Map from watch descriptors to watched paths
    221     std::unordered_map<int, std::string> mWatchedPaths;
    222     // Map from file descriptors to InputDeviceNodes
    223     std::unordered_map<int, std::shared_ptr<InputDeviceNode>> mDeviceNodes;
    224 };
    225 
    226 }  // namespace android
    227 
    228 #endif  // ANDROID_INPUT_HUB_H_
    229