173ac368aSBen Tyner #include "attn_monitor.hpp"
273ac368aSBen Tyner 
373ac368aSBen Tyner #include "attn_handler.hpp"
473ac368aSBen Tyner 
59ae5ca41SBen Tyner #include <logging.hpp>
673ac368aSBen Tyner 
773ac368aSBen Tyner namespace attn
873ac368aSBen Tyner {
973ac368aSBen Tyner 
1073ac368aSBen Tyner /** @brief Register a callback for gpio event */
1173ac368aSBen Tyner void AttnMonitor::scheduleGPIOEvent()
1273ac368aSBen Tyner {
139ae5ca41SBen Tyner     std::string logMessage = "... waiting for events ...";
1473ac368aSBen Tyner     log<level::INFO>(logMessage.c_str());
1573ac368aSBen Tyner 
1673ac368aSBen Tyner     // Register async callback, note that callback is a
1773ac368aSBen Tyner     // lambda function with "this" pointer captured
1873ac368aSBen Tyner     iv_gpioEventDescriptor.async_wait(
1973ac368aSBen Tyner         boost::asio::posix::stream_descriptor::wait_read,
2073ac368aSBen Tyner         [this](const boost::system::error_code& ec) {
2173ac368aSBen Tyner             if (ec)
2273ac368aSBen Tyner             {
239ae5ca41SBen Tyner                 std::string logMessage =
249ae5ca41SBen Tyner                     "GPIO Async wait error: " + std::string(ec.message());
2573ac368aSBen Tyner                 log<level::INFO>(logMessage.c_str());
2673ac368aSBen Tyner             }
2773ac368aSBen Tyner             else
2873ac368aSBen Tyner             {
2973ac368aSBen Tyner                 handleGPIOEvent(); // gpio trigger detected
3073ac368aSBen Tyner             }
3173ac368aSBen Tyner             return;
3273ac368aSBen Tyner         }); // register async callback
3373ac368aSBen Tyner }
3473ac368aSBen Tyner 
3573ac368aSBen Tyner /** @brief Handle the GPIO state change event */
3673ac368aSBen Tyner void AttnMonitor::handleGPIOEvent()
3773ac368aSBen Tyner {
3873ac368aSBen Tyner     gpiod_line_event gpioEvent;
3973ac368aSBen Tyner     std::string logMessage;
4073ac368aSBen Tyner 
4173ac368aSBen Tyner     if (gpiod_line_event_read_fd(iv_gpioEventDescriptor.native_handle(),
4273ac368aSBen Tyner                                  &gpioEvent) < 0)
4373ac368aSBen Tyner     {
449ae5ca41SBen Tyner         logMessage = "GPIO line read failed";
4573ac368aSBen Tyner         log<level::INFO>(logMessage.c_str());
4673ac368aSBen Tyner     }
4773ac368aSBen Tyner     else
4873ac368aSBen Tyner     {
4973ac368aSBen Tyner         switch (gpiod_line_get_value(iv_gpioLine))
5073ac368aSBen Tyner         {
5173ac368aSBen Tyner             // active attention when gpio == 0
5273ac368aSBen Tyner             case 0:
53*3fb52e53SBen Tyner                 attnHandler(iv_config);
5473ac368aSBen Tyner                 break;
5573ac368aSBen Tyner 
5673ac368aSBen Tyner             // gpio == 1, GPIO handler should not be executing
5773ac368aSBen Tyner             case 1:
589ae5ca41SBen Tyner                 logMessage = "GPIO handler out of sync";
5973ac368aSBen Tyner                 log<level::INFO>(logMessage.c_str());
6073ac368aSBen Tyner                 break;
6173ac368aSBen Tyner 
6273ac368aSBen Tyner             // unexpected value
6373ac368aSBen Tyner             default:
649ae5ca41SBen Tyner                 logMessage = "GPIO line unexpected value";
6573ac368aSBen Tyner                 log<level::INFO>(logMessage.c_str());
6673ac368aSBen Tyner         }
6773ac368aSBen Tyner     }
6873ac368aSBen Tyner     scheduleGPIOEvent(); // continue monitoring gpio
6973ac368aSBen Tyner }
7073ac368aSBen Tyner 
7173ac368aSBen Tyner /** @brief Request a GPIO line for monitoring attention events */
7273ac368aSBen Tyner void AttnMonitor::requestGPIOEvent()
7373ac368aSBen Tyner {
7473ac368aSBen Tyner     if (0 != gpiod_line_request(iv_gpioLine, &iv_gpioConfig, 0))
7573ac368aSBen Tyner     {
769ae5ca41SBen Tyner         std::string logMessage = "failed request for GPIO";
7773ac368aSBen Tyner         log<level::INFO>(logMessage.c_str());
7873ac368aSBen Tyner     }
7973ac368aSBen Tyner     else
8073ac368aSBen Tyner     {
8173ac368aSBen Tyner         int gpioLineFd;
8273ac368aSBen Tyner 
8373ac368aSBen Tyner         gpioLineFd = gpiod_line_event_get_fd(iv_gpioLine);
8473ac368aSBen Tyner         if (gpioLineFd < 0)
8573ac368aSBen Tyner         {
869ae5ca41SBen Tyner             std::string logMessage = "failed to get file descriptor";
8773ac368aSBen Tyner             log<level::INFO>(logMessage.c_str());
8873ac368aSBen Tyner         }
8973ac368aSBen Tyner         else
9073ac368aSBen Tyner         {
9173ac368aSBen Tyner             // Register file descriptor for monitoring
9273ac368aSBen Tyner             iv_gpioEventDescriptor.assign(gpioLineFd);
9373ac368aSBen Tyner 
9473ac368aSBen Tyner             // Start monitoring
9573ac368aSBen Tyner             scheduleGPIOEvent();
9673ac368aSBen Tyner         }
9773ac368aSBen Tyner     }
9873ac368aSBen Tyner }
9973ac368aSBen Tyner 
10073ac368aSBen Tyner } // namespace attn
101