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