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