summaryrefslogtreecommitdiffstats
path: root/evdev.hpp
blob: b3189f10aa67a58854bb2f645bcfabd3f2320c35 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#pragma once
#include <string>
#include <systemd/sd-event.h>
#include <libevdev/libevdev.h>
#include "file.hpp"

namespace phosphor
{
namespace gpio
{

/* Need a custom deleter for freeing up sd_event */
struct EventDeleter
{
    void operator()(sd_event* event) const
    {
        event = sd_event_unref(event);
    }
};
using EventPtr = std::unique_ptr<sd_event, EventDeleter>;

/* Need a custom deleter for freeing up sd_event_source */
struct EventSourceDeleter
{
    void operator()(sd_event_source* eventSource) const
    {
        eventSource = sd_event_source_unref(eventSource);
    }
};
using EventSourcePtr = std::unique_ptr<sd_event_source, EventSourceDeleter>;

/* Need a custom deleter for freeing up evdev struct */
struct FreeEvDev
{
    void operator()(struct libevdev* device) const
    {
        libevdev_free(device);
    }
};
using EvdevPtr = std::unique_ptr<struct libevdev, FreeEvDev>;

/** @class Evdev
 *  @brief Responsible for catching GPIO state changes conditions and taking
 *  actions
 */
class Evdev
{

        using Property = std::string;
        using Value = sdbusplus::message::variant<bool, std::string>;
        // Association between property and its value
        using PropertyMap = std::map<Property, Value>;
        using Interface = std::string;
        // Association between interface and the D-Bus property
        using InterfaceMap = std::map<Interface, PropertyMap>;
        using Object = sdbusplus::message::object_path;
        // Association between object and the interface
        using ObjectMap = std::map<Object, InterfaceMap>;

    public:
        Evdev() = delete;
        ~Evdev() = default;
        Evdev(const Evdev&) = delete;
        Evdev& operator=(const Evdev&) = delete;
        Evdev(Evdev&&) = delete;
        Evdev& operator=(Evdev&&) = delete;

        /** @brief Constructs Evdev object.
         *
         *  @param[in] path      - Device path to read for GPIO pin state
         *  @param[in] key       - GPIO key to monitor
         *  @param[in] event     - sd_event handler
         *  @param[in] handler   - IO callback handler. Defaults to one in this
         *                        class
         *  @param[in] useEvDev  - Whether to use EvDev to retrieve events
         */
        Evdev(const std::string& path,
              const unsigned int key,
              EventPtr& event,
              sd_event_io_handler_t handler,
              bool useEvDev = true) :
            path(path),
            key(key),
            event(event),
            callbackHandler(handler),
            fd(openDevice())

        {
            if (useEvDev)
            {
                // If we are asked to use EvDev, do that initialization.
                initEvDev();
            }

            // Register callback handler when FD has some data
            registerCallback();
        }

    protected:
        /** @brief Device path to read for GPIO pin state */
        const std::string path;

        /** @brief GPIO key to monitor */
        const unsigned int key;

        /** @brief Event structure */
        EvdevPtr devicePtr;

        /** @brief Monitor to sd_event */
        EventPtr& event;

        /** @brief Callback handler when the FD has some data */
        sd_event_io_handler_t callbackHandler;

        /** @brief event source */
        EventSourcePtr eventSource;

        /** @brief Opens the device and populates the descriptor */
        int openDevice();

        /** @brief attaches FD to events and sets up callback handler */
        void registerCallback();

        /** @brief File descriptor manager */
        FileDescriptor fd;

        /** @brief Initializes evdev handle with the fd */
        void initEvDev();
};

} // namespace gpio
} // namespace phosphor
OpenPOWER on IntegriCloud