blob: 543729ceed69161b5d965e46994e65443a857dad [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. */
Patrick Williams61b73292023-05-10 07:50:12 -050068 explicit EvDev(EvDevPtr ptr) : evdev(ptr) {}
Brad Bishop8a502f52017-06-14 23:46:15 -040069
Matthew Barth11fc0a72020-05-26 10:55:54 -050070 /** @brief Get the current event state. */
71 auto fetch(unsigned int type, unsigned int code)
72 {
73 int val;
74 auto rc = libevdev_fetch_event_value(evdev.get(), type, code, &val);
75 if (!rc)
Brad Bishop8a502f52017-06-14 23:46:15 -040076 {
Matthew Barth11fc0a72020-05-26 10:55:54 -050077 log<level::ERR>("Error in call to libevdev_fetch_event_value",
78 entry("TYPE=%d", type), entry("CODE=%d", code));
79 elog<InternalFailure>();
80 }
81
82 return val;
83 }
84
85 /** @brief Get the next event. */
86 auto next()
87 {
88 struct input_event ev;
89 while (true)
90 {
91 auto rc = libevdev_next_event(evdev.get(),
92 LIBEVDEV_READ_FLAG_NORMAL, &ev);
93 if (rc < 0)
Brad Bishop8a502f52017-06-14 23:46:15 -040094 {
Matthew Barth11fc0a72020-05-26 10:55:54 -050095 log<level::ERR>("Error in call to libevdev_next_event",
96 entry("RC=%d", rc));
Marri Devender Rao60885582017-11-07 04:58:14 -060097 elog<InternalFailure>();
Brad Bishop8a502f52017-06-14 23:46:15 -040098 }
99
Matthew Barth11fc0a72020-05-26 10:55:54 -0500100 if (ev.type == EV_SYN && ev.code == SYN_REPORT)
101 continue;
102
103 break;
Brad Bishop8a502f52017-06-14 23:46:15 -0400104 }
Matthew Barth11fc0a72020-05-26 10:55:54 -0500105 return std::make_tuple(ev.type, ev.code, ev.value);
106 }
Brad Bishop8a502f52017-06-14 23:46:15 -0400107
Matthew Barth11fc0a72020-05-26 10:55:54 -0500108 private:
109 EvDevPtr get()
110 {
111 return evdev.get();
112 }
Brad Bishop8a502f52017-06-14 23:46:15 -0400113
Matthew Barth11fc0a72020-05-26 10:55:54 -0500114 details::EvDev evdev;
Brad Bishop8a502f52017-06-14 23:46:15 -0400115};
116
117inline auto newFromFD(int fd)
118{
Matthew Barth11fc0a72020-05-26 10:55:54 -0500119 using InternalFailure =
120 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Brad Bishop8a502f52017-06-14 23:46:15 -0400121
122 EvDevPtr dev = nullptr;
123 auto rc = libevdev_new_from_fd(fd, &dev);
124
125 if (rc)
126 {
Marri Devender Rao60885582017-11-07 04:58:14 -0600127 log<level::ERR>("Error in call to libevdev_new_from_fd",
Matthew Barth11fc0a72020-05-26 10:55:54 -0500128 entry("RC=%d", rc), entry("FD=%d", fd));
Marri Devender Rao60885582017-11-07 04:58:14 -0600129 elog<InternalFailure>();
Brad Bishop8a502f52017-06-14 23:46:15 -0400130 }
131
132 return EvDev(dev);
133}
134} // namespace evdev
135} // namespace evdevpp