blob: 0bd0f4c4fbabdfbfaa4118c1cd99aa2dd350449d [file] [log] [blame]
#include "GPIOInterface.hpp"
#include <gpiod.hpp>
#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/async.hpp>
#include <exception>
#include <memory>
#include <stdexcept>
#include <string>
#include <utility>
namespace gpio
{
PHOSPHOR_LOG2_USING;
GPIOInterface::GPIOInterface(sdbusplus::async::context& ctx,
const std::string& consumerName,
const std::string& pinName, bool activeLow,
Callback_t updateStateCallback) :
ctx(ctx), pinName(pinName),
updateStateCallback(std::move(updateStateCallback))
{
if (!this->updateStateCallback)
{
throw std::runtime_error("updateStateCallback is not set");
}
line = gpiod::find_line(pinName);
if (!line)
{
throw std::runtime_error("Failed to find GPIO line for " + pinName);
}
try
{
line.request({consumerName, gpiod::line_request::EVENT_BOTH_EDGES,
activeLow ? gpiod::line_request::FLAG_ACTIVE_LOW : 0});
}
catch (std::exception& e)
{
throw std::runtime_error("Failed to request line for " + pinName +
" with error " + e.what());
}
int lineFd = line.event_get_fd();
if (lineFd < 0)
{
throw std::runtime_error(
"Failed to get event fd for GPIO line " + pinName);
}
fdioInstance = std::make_unique<sdbusplus::async::fdio>(ctx, lineFd);
}
auto GPIOInterface::start() -> sdbusplus::async::task<>
{
// Start the async read for the GPIO line
ctx.spawn(readGPIOAsyncEvent());
// Read the initial GPIO value
co_await readGPIOAsync();
}
auto GPIOInterface::readGPIOAsync() -> sdbusplus::async::task<>
{
auto lineValue = line.get_value();
if (lineValue < 0)
{
error("Failed to read GPIO line {LINENAME}", "LINENAME", pinName);
co_return;
}
co_await updateStateCallback(lineValue == gpiod::line_event::RISING_EDGE);
co_return;
}
auto GPIOInterface::readGPIOAsyncEvent() -> sdbusplus::async::task<>
{
while (!ctx.stop_requested())
{
// Wait for the fd event for the line to change
co_await fdioInstance->next();
line.event_read();
auto lineValue = line.get_value();
co_await updateStateCallback(
lineValue == gpiod::line_event::RISING_EDGE);
}
co_return;
}
} // namespace gpio