xref: /openbmc/phosphor-gpio-monitor/evdev.cpp (revision 835dfb8877fd2e78281e22b8b08dc29e0e9ef5a5)
1*835dfb88SGunnar Mills #include <libevdev/libevdev.h>
2*835dfb88SGunnar Mills #include <fcntl.h>
3*835dfb88SGunnar Mills #include <phosphor-logging/elog.hpp>
4*835dfb88SGunnar Mills #include <phosphor-logging/log.hpp>
5*835dfb88SGunnar Mills #include <phosphor-logging/elog-errors.hpp>
6*835dfb88SGunnar Mills #include "xyz/openbmc_project/Common/error.hpp"
7*835dfb88SGunnar Mills #include "evdev.hpp"
8*835dfb88SGunnar Mills 
9*835dfb88SGunnar Mills namespace phosphor
10*835dfb88SGunnar Mills {
11*835dfb88SGunnar Mills namespace gpio
12*835dfb88SGunnar Mills {
13*835dfb88SGunnar Mills 
14*835dfb88SGunnar Mills using namespace phosphor::logging;
15*835dfb88SGunnar Mills using namespace sdbusplus::xyz::openbmc_project::Common::Error;
16*835dfb88SGunnar Mills 
17*835dfb88SGunnar Mills // Populate the file descriptor for passed in device
18*835dfb88SGunnar Mills int Evdev::openDevice()
19*835dfb88SGunnar Mills {
20*835dfb88SGunnar Mills     using namespace phosphor::logging;
21*835dfb88SGunnar Mills 
22*835dfb88SGunnar Mills     auto fd = open(path.c_str(), O_RDONLY | O_NONBLOCK);
23*835dfb88SGunnar Mills     if (fd < 0)
24*835dfb88SGunnar Mills     {
25*835dfb88SGunnar Mills         log<level::ERR>("Failed to open device path",
26*835dfb88SGunnar Mills                         entry("DEVICEPATH=%s", path.c_str()),
27*835dfb88SGunnar Mills                         entry("ERRNO=%d", errno));
28*835dfb88SGunnar Mills         elog<InternalFailure>();
29*835dfb88SGunnar Mills     }
30*835dfb88SGunnar Mills     return fd;
31*835dfb88SGunnar Mills }
32*835dfb88SGunnar Mills 
33*835dfb88SGunnar Mills // Initializes the event device with the fd
34*835dfb88SGunnar Mills void Evdev::initEvDev()
35*835dfb88SGunnar Mills {
36*835dfb88SGunnar Mills     if (devicePtr)
37*835dfb88SGunnar Mills     {
38*835dfb88SGunnar Mills         // Init can be done only once per device
39*835dfb88SGunnar Mills         return;
40*835dfb88SGunnar Mills     }
41*835dfb88SGunnar Mills 
42*835dfb88SGunnar Mills     struct libevdev* evdev = nullptr;
43*835dfb88SGunnar Mills     auto rc = libevdev_new_from_fd((fd)(), &evdev);
44*835dfb88SGunnar Mills     if (rc < 0)
45*835dfb88SGunnar Mills     {
46*835dfb88SGunnar Mills         log<level::ERR>("Failed to initialize evdev");
47*835dfb88SGunnar Mills         elog<InternalFailure>();
48*835dfb88SGunnar Mills         return;
49*835dfb88SGunnar Mills     }
50*835dfb88SGunnar Mills 
51*835dfb88SGunnar Mills     // Packing in the unique_ptr
52*835dfb88SGunnar Mills     devicePtr.reset(evdev);
53*835dfb88SGunnar Mills }
54*835dfb88SGunnar Mills 
55*835dfb88SGunnar Mills // Attaches the FD to event loop and registers the callback handler
56*835dfb88SGunnar Mills void Evdev::registerCallback()
57*835dfb88SGunnar Mills {
58*835dfb88SGunnar Mills     decltype(eventSource.get()) sourcePtr = nullptr;
59*835dfb88SGunnar Mills     auto rc = sd_event_add_io(event.get(), &sourcePtr, (fd)(),
60*835dfb88SGunnar Mills                               EPOLLIN, callbackHandler, this);
61*835dfb88SGunnar Mills     eventSource.reset(sourcePtr);
62*835dfb88SGunnar Mills 
63*835dfb88SGunnar Mills     if (rc < 0)
64*835dfb88SGunnar Mills     {
65*835dfb88SGunnar Mills         log<level::ERR>("Failed to register callback handler",
66*835dfb88SGunnar Mills                         entry("ERROR=%s", strerror(-rc)));
67*835dfb88SGunnar Mills         elog<InternalFailure>();
68*835dfb88SGunnar Mills     }
69*835dfb88SGunnar Mills }
70*835dfb88SGunnar Mills 
71*835dfb88SGunnar Mills } // namespace gpio
72*835dfb88SGunnar Mills } // namespace phosphor
73