xref: /openbmc/dbus-sensors/src/GPIOInterface.cpp (revision 15dde8641baa1cb902d17f9857effb081e384944)
1*15dde864SJagpal Singh Gill #include "GPIOInterface.hpp"
2*15dde864SJagpal Singh Gill 
3*15dde864SJagpal Singh Gill #include <gpiod.hpp>
4*15dde864SJagpal Singh Gill #include <phosphor-logging/lg2.hpp>
5*15dde864SJagpal Singh Gill #include <sdbusplus/async.hpp>
6*15dde864SJagpal Singh Gill 
7*15dde864SJagpal Singh Gill #include <exception>
8*15dde864SJagpal Singh Gill #include <memory>
9*15dde864SJagpal Singh Gill #include <stdexcept>
10*15dde864SJagpal Singh Gill #include <string>
11*15dde864SJagpal Singh Gill #include <utility>
12*15dde864SJagpal Singh Gill 
13*15dde864SJagpal Singh Gill namespace gpio
14*15dde864SJagpal Singh Gill {
15*15dde864SJagpal Singh Gill 
16*15dde864SJagpal Singh Gill PHOSPHOR_LOG2_USING;
17*15dde864SJagpal Singh Gill 
GPIOInterface(sdbusplus::async::context & ctx,const std::string & consumerName,const std::string & pinName,bool activeLow,Callback_t updateStateCallback)18*15dde864SJagpal Singh Gill GPIOInterface::GPIOInterface(sdbusplus::async::context& ctx,
19*15dde864SJagpal Singh Gill                              const std::string& consumerName,
20*15dde864SJagpal Singh Gill                              const std::string& pinName, bool activeLow,
21*15dde864SJagpal Singh Gill                              Callback_t updateStateCallback) :
22*15dde864SJagpal Singh Gill     ctx(ctx), pinName(pinName),
23*15dde864SJagpal Singh Gill     updateStateCallback(std::move(updateStateCallback))
24*15dde864SJagpal Singh Gill {
25*15dde864SJagpal Singh Gill     if (!this->updateStateCallback)
26*15dde864SJagpal Singh Gill     {
27*15dde864SJagpal Singh Gill         throw std::runtime_error("updateStateCallback is not set");
28*15dde864SJagpal Singh Gill     }
29*15dde864SJagpal Singh Gill     line = gpiod::find_line(pinName);
30*15dde864SJagpal Singh Gill     if (!line)
31*15dde864SJagpal Singh Gill     {
32*15dde864SJagpal Singh Gill         throw std::runtime_error("Failed to find GPIO line for " + pinName);
33*15dde864SJagpal Singh Gill     }
34*15dde864SJagpal Singh Gill     try
35*15dde864SJagpal Singh Gill     {
36*15dde864SJagpal Singh Gill         line.request({consumerName, gpiod::line_request::EVENT_BOTH_EDGES,
37*15dde864SJagpal Singh Gill                       activeLow ? gpiod::line_request::FLAG_ACTIVE_LOW : 0});
38*15dde864SJagpal Singh Gill     }
39*15dde864SJagpal Singh Gill     catch (std::exception& e)
40*15dde864SJagpal Singh Gill     {
41*15dde864SJagpal Singh Gill         throw std::runtime_error("Failed to request line for " + pinName +
42*15dde864SJagpal Singh Gill                                  " with error " + e.what());
43*15dde864SJagpal Singh Gill     }
44*15dde864SJagpal Singh Gill 
45*15dde864SJagpal Singh Gill     int lineFd = line.event_get_fd();
46*15dde864SJagpal Singh Gill     if (lineFd < 0)
47*15dde864SJagpal Singh Gill     {
48*15dde864SJagpal Singh Gill         throw std::runtime_error(
49*15dde864SJagpal Singh Gill             "Failed to get event fd for GPIO line " + pinName);
50*15dde864SJagpal Singh Gill     }
51*15dde864SJagpal Singh Gill 
52*15dde864SJagpal Singh Gill     fdioInstance = std::make_unique<sdbusplus::async::fdio>(ctx, lineFd);
53*15dde864SJagpal Singh Gill }
54*15dde864SJagpal Singh Gill 
start()55*15dde864SJagpal Singh Gill auto GPIOInterface::start() -> sdbusplus::async::task<>
56*15dde864SJagpal Singh Gill {
57*15dde864SJagpal Singh Gill     // Start the async read for the GPIO line
58*15dde864SJagpal Singh Gill     ctx.spawn(readGPIOAsyncEvent());
59*15dde864SJagpal Singh Gill 
60*15dde864SJagpal Singh Gill     // Read the initial GPIO value
61*15dde864SJagpal Singh Gill     co_await readGPIOAsync();
62*15dde864SJagpal Singh Gill }
63*15dde864SJagpal Singh Gill 
readGPIOAsync()64*15dde864SJagpal Singh Gill auto GPIOInterface::readGPIOAsync() -> sdbusplus::async::task<>
65*15dde864SJagpal Singh Gill {
66*15dde864SJagpal Singh Gill     auto lineValue = line.get_value();
67*15dde864SJagpal Singh Gill     if (lineValue < 0)
68*15dde864SJagpal Singh Gill     {
69*15dde864SJagpal Singh Gill         error("Failed to read GPIO line {LINENAME}", "LINENAME", pinName);
70*15dde864SJagpal Singh Gill         co_return;
71*15dde864SJagpal Singh Gill     }
72*15dde864SJagpal Singh Gill     co_await updateStateCallback(lineValue == gpiod::line_event::RISING_EDGE);
73*15dde864SJagpal Singh Gill 
74*15dde864SJagpal Singh Gill     co_return;
75*15dde864SJagpal Singh Gill }
76*15dde864SJagpal Singh Gill 
readGPIOAsyncEvent()77*15dde864SJagpal Singh Gill auto GPIOInterface::readGPIOAsyncEvent() -> sdbusplus::async::task<>
78*15dde864SJagpal Singh Gill {
79*15dde864SJagpal Singh Gill     while (!ctx.stop_requested())
80*15dde864SJagpal Singh Gill     {
81*15dde864SJagpal Singh Gill         // Wait for the fd event for the line to change
82*15dde864SJagpal Singh Gill         co_await fdioInstance->next();
83*15dde864SJagpal Singh Gill 
84*15dde864SJagpal Singh Gill         line.event_read();
85*15dde864SJagpal Singh Gill         auto lineValue = line.get_value();
86*15dde864SJagpal Singh Gill 
87*15dde864SJagpal Singh Gill         co_await updateStateCallback(
88*15dde864SJagpal Singh Gill             lineValue == gpiod::line_event::RISING_EDGE);
89*15dde864SJagpal Singh Gill     }
90*15dde864SJagpal Singh Gill 
91*15dde864SJagpal Singh Gill     co_return;
92*15dde864SJagpal Singh Gill }
93*15dde864SJagpal Singh Gill 
94*15dde864SJagpal Singh Gill } // namespace gpio
95