blob: 18619825af485f1076fc33686bfd049b1268d5a1 [file] [log] [blame]
Brad Bishop8a502f52017-06-14 23:46:15 -04001#pragma once
2
3#include <fcntl.h>
4#include <libevdev/libevdev.h>
5#include <memory>
6#include <phosphor-logging/elog.hpp>
7#include <phosphor-logging/elog-errors.hpp>
8#include <string>
9#include <tuple>
10#include <unistd.h>
11#include <xyz/openbmc_project/Common/error.hpp>
12
13namespace evdevpp
14{
15namespace evdev
16{
17
18using EvDevPtr = libevdev*;
19
20namespace details
21{
22
23/** @brief unique_ptr functor to release an evdev reference. */
24struct EvDevDeleter
25{
26 void operator()(libevdev* ptr) const
27 {
28 deleter(ptr);
29 }
30
31 decltype(&libevdev_free) deleter = libevdev_free;
32};
33
34/* @brief Alias evdev to a unique_ptr type for auto-release. */
35using EvDev = std::unique_ptr<libevdev, EvDevDeleter>;
36
37} // namespace details
38
39/** @class EvDev
40 * @brief Provides C++ bindings to the libevdev C API.
41 */
42class EvDev
43{
44 private:
45 using InternalFailure = sdbusplus::xyz::openbmc_project::Common::
46 Error::InternalFailure;
47
48 public:
49 /* Define all of the basic class operations:
50 * Not allowed:
51 * - Default constructor to avoid nullptrs.
52 * - Copy operations due to internal unique_ptr.
53 * Allowed:
54 * - Move operations.
55 * - Destructor.
56 */
57 EvDev() = delete;
58 EvDev(const EvDev&) = delete;
59 EvDev& operator=(const EvDev&) = delete;
60 EvDev(EvDev&&) = default;
61 EvDev& operator=(EvDev&&) = default;
62 ~EvDev() = default;
63
64 /** @brief Conversion constructor from evdev. */
65 explicit EvDev(EvDevPtr ptr) : evdev(ptr) {}
66
67 /** @brief Get the current event state. */
68 auto fetch(unsigned int type, unsigned int code)
69 {
70 int val;
71 auto rc = libevdev_fetch_event_value(
72 evdev.get(), type, code, &val);
73 if (!rc)
74 {
75 phosphor::logging::elog<InternalFailure>();
76 }
77
78 return val;
79 }
80
81 /** @brief Get the next event. */
82 auto next()
83 {
84 struct input_event ev;
85 while (true)
86 {
87 auto rc = libevdev_next_event(
88 evdev.get(), LIBEVDEV_READ_FLAG_NORMAL, &ev);
89 if (rc < 0)
90 {
91 phosphor::logging::elog<InternalFailure>();
92 }
93
94 if (ev.type == EV_SYN && ev.code == SYN_REPORT)
95 continue;
96
97 break;
98 }
99 return std::make_tuple(ev.type, ev.code, ev.value);
100 }
101
102 private:
103 EvDevPtr get()
104 {
105 return evdev.get();
106 }
107
108 details::EvDev evdev;
109};
110
111inline auto newFromFD(int fd)
112{
113 using InternalFailure = sdbusplus::xyz::openbmc_project::Common::
114 Error::InternalFailure;
115
116 EvDevPtr dev = nullptr;
117 auto rc = libevdev_new_from_fd(fd, &dev);
118
119 if (rc)
120 {
121 phosphor::logging::elog<InternalFailure>();
122 }
123
124 return EvDev(dev);
125}
126} // namespace evdev
127} // namespace evdevpp