| #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 |