blob: ae9a370b3019c3817b552b14aef301b337598950 [file] [log] [blame]
Brad Bishop8a502f52017-06-14 23:46:15 -04001#pragma once
2
3#include <fcntl.h>
4#include <libevdev/libevdev.h>
Matthew Barth11fc0a72020-05-26 10:55:54 -05005#include <unistd.h>
6
Brad Bishop8a502f52017-06-14 23:46:15 -04007#include <phosphor-logging/elog-errors.hpp>
Matthew Barth11fc0a72020-05-26 10:55:54 -05008#include <phosphor-logging/elog.hpp>
9#include <xyz/openbmc_project/Common/error.hpp>
10
11#include <memory>
Brad Bishop8a502f52017-06-14 23:46:15 -040012#include <string>
13#include <tuple>
Brad Bishop8a502f52017-06-14 23:46:15 -040014
15namespace evdevpp
16{
17namespace evdev
18{
19
20using EvDevPtr = libevdev*;
21
22namespace details
23{
24
25/** @brief unique_ptr functor to release an evdev reference. */
26struct EvDevDeleter
27{
28 void operator()(libevdev* ptr) const
29 {
30 deleter(ptr);
31 }
32
33 decltype(&libevdev_free) deleter = libevdev_free;
34};
35
36/* @brief Alias evdev to a unique_ptr type for auto-release. */
37using EvDev = std::unique_ptr<libevdev, EvDevDeleter>;
38
39} // namespace details
40
Marri Devender Rao60885582017-11-07 04:58:14 -060041using namespace phosphor::logging;
Brad Bishop8a502f52017-06-14 23:46:15 -040042/** @class EvDev
43 * @brief Provides C++ bindings to the libevdev C API.
44 */
45class EvDev
46{
Matthew Barth11fc0a72020-05-26 10:55:54 -050047 private:
48 using InternalFailure =
49 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Brad Bishop8a502f52017-06-14 23:46:15 -040050
Matthew Barth11fc0a72020-05-26 10:55:54 -050051 public:
52 /* Define all of the basic class operations:
53 * Not allowed:
54 * - Default constructor to avoid nullptrs.
55 * - Copy operations due to internal unique_ptr.
56 * Allowed:
57 * - Move operations.
58 * - Destructor.
59 */
60 EvDev() = delete;
61 EvDev(const EvDev&) = delete;
62 EvDev& operator=(const EvDev&) = delete;
63 EvDev(EvDev&&) = default;
64 EvDev& operator=(EvDev&&) = default;
65 ~EvDev() = default;
Brad Bishop8a502f52017-06-14 23:46:15 -040066
Matthew Barth11fc0a72020-05-26 10:55:54 -050067 /** @brief Conversion constructor from evdev. */
68 explicit EvDev(EvDevPtr ptr) : evdev(ptr)
69 {}
Brad Bishop8a502f52017-06-14 23:46:15 -040070
Matthew Barth11fc0a72020-05-26 10:55:54 -050071 /** @brief Get the current event state. */
72 auto fetch(unsigned int type, unsigned int code)
73 {
74 int val;
75 auto rc = libevdev_fetch_event_value(evdev.get(), type, code, &val);
76 if (!rc)
Brad Bishop8a502f52017-06-14 23:46:15 -040077 {
Matthew Barth11fc0a72020-05-26 10:55:54 -050078 log<level::ERR>("Error in call to libevdev_fetch_event_value",
79 entry("TYPE=%d", type), entry("CODE=%d", code));
80 elog<InternalFailure>();
81 }
82
83 return val;
84 }
85
86 /** @brief Get the next event. */
87 auto next()
88 {
89 struct input_event ev;
90 while (true)
91 {
92 auto rc = libevdev_next_event(evdev.get(),
93 LIBEVDEV_READ_FLAG_NORMAL, &ev);
94 if (rc < 0)
Brad Bishop8a502f52017-06-14 23:46:15 -040095 {
Matthew Barth11fc0a72020-05-26 10:55:54 -050096 log<level::ERR>("Error in call to libevdev_next_event",
97 entry("RC=%d", rc));
Marri Devender Rao60885582017-11-07 04:58:14 -060098 elog<InternalFailure>();
Brad Bishop8a502f52017-06-14 23:46:15 -040099 }
100
Matthew Barth11fc0a72020-05-26 10:55:54 -0500101 if (ev.type == EV_SYN && ev.code == SYN_REPORT)
102 continue;
103
104 break;
Brad Bishop8a502f52017-06-14 23:46:15 -0400105 }
Matthew Barth11fc0a72020-05-26 10:55:54 -0500106 return std::make_tuple(ev.type, ev.code, ev.value);
107 }
Brad Bishop8a502f52017-06-14 23:46:15 -0400108
Matthew Barth11fc0a72020-05-26 10:55:54 -0500109 private:
110 EvDevPtr get()
111 {
112 return evdev.get();
113 }
Brad Bishop8a502f52017-06-14 23:46:15 -0400114
Matthew Barth11fc0a72020-05-26 10:55:54 -0500115 details::EvDev evdev;
Brad Bishop8a502f52017-06-14 23:46:15 -0400116};
117
118inline auto newFromFD(int fd)
119{
Matthew Barth11fc0a72020-05-26 10:55:54 -0500120 using InternalFailure =
121 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Brad Bishop8a502f52017-06-14 23:46:15 -0400122
123 EvDevPtr dev = nullptr;
124 auto rc = libevdev_new_from_fd(fd, &dev);
125
126 if (rc)
127 {
Marri Devender Rao60885582017-11-07 04:58:14 -0600128 log<level::ERR>("Error in call to libevdev_new_from_fd",
Matthew Barth11fc0a72020-05-26 10:55:54 -0500129 entry("RC=%d", rc), entry("FD=%d", fd));
Marri Devender Rao60885582017-11-07 04:58:14 -0600130 elog<InternalFailure>();
Brad Bishop8a502f52017-06-14 23:46:15 -0400131 }
132
133 return EvDev(dev);
134}
135} // namespace evdev
136} // namespace evdevpp