#include "GPIOInterface.hpp" #include #include #include #include #include #include #include #include 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(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