1*b797b3e1SBen Tyner #include <attn/attn_handler.hpp>
2*b797b3e1SBen Tyner #include <attn/attn_logging.hpp>
3*b797b3e1SBen Tyner #include <attn/attn_monitor.hpp>
473ac368aSBen Tyner 
573ac368aSBen Tyner namespace attn
673ac368aSBen Tyner {
773ac368aSBen Tyner 
873ac368aSBen Tyner /** @brief Register a callback for gpio event */
973ac368aSBen Tyner void AttnMonitor::scheduleGPIOEvent()
1073ac368aSBen Tyner {
119ae5ca41SBen Tyner     std::string logMessage = "... waiting for events ...";
12b1ebfcb1SBen Tyner     trace<level::INFO>(logMessage.c_str());
1373ac368aSBen Tyner 
1473ac368aSBen Tyner     // Register async callback, note that callback is a
1573ac368aSBen Tyner     // lambda function with "this" pointer captured
1673ac368aSBen Tyner     iv_gpioEventDescriptor.async_wait(
1773ac368aSBen Tyner         boost::asio::posix::stream_descriptor::wait_read,
1873ac368aSBen Tyner         [this](const boost::system::error_code& ec) {
1973ac368aSBen Tyner             if (ec)
2073ac368aSBen Tyner             {
219ae5ca41SBen Tyner                 std::string logMessage =
229ae5ca41SBen Tyner                     "GPIO Async wait error: " + std::string(ec.message());
23b1ebfcb1SBen Tyner                 trace<level::INFO>(logMessage.c_str());
2473ac368aSBen Tyner             }
2573ac368aSBen Tyner             else
2673ac368aSBen Tyner             {
27b1ebfcb1SBen Tyner                 trace<level::INFO>(
28b1ebfcb1SBen Tyner                     "Attention monitor detected active attention");
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";
45b1ebfcb1SBen Tyner         trace<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:
53117af99bSBen Tyner                 logMessage = "Attention monitor calling attention handler";
54b1ebfcb1SBen Tyner                 trace<level::INFO>(logMessage.c_str());
553fb52e53SBen Tyner                 attnHandler(iv_config);
5673ac368aSBen Tyner                 break;
5773ac368aSBen Tyner 
5873ac368aSBen Tyner             // gpio == 1, GPIO handler should not be executing
5973ac368aSBen Tyner             case 1:
609ae5ca41SBen Tyner                 logMessage = "GPIO handler out of sync";
61b1ebfcb1SBen Tyner                 trace<level::INFO>(logMessage.c_str());
6273ac368aSBen Tyner                 break;
6373ac368aSBen Tyner 
6473ac368aSBen Tyner             // unexpected value
6573ac368aSBen Tyner             default:
669ae5ca41SBen Tyner                 logMessage = "GPIO line unexpected value";
67b1ebfcb1SBen Tyner                 trace<level::INFO>(logMessage.c_str());
6873ac368aSBen Tyner         }
6973ac368aSBen Tyner     }
7073ac368aSBen Tyner     scheduleGPIOEvent(); // continue monitoring gpio
7173ac368aSBen Tyner }
7273ac368aSBen Tyner 
7373ac368aSBen Tyner /** @brief Request a GPIO line for monitoring attention events */
7473ac368aSBen Tyner void AttnMonitor::requestGPIOEvent()
7573ac368aSBen Tyner {
7673ac368aSBen Tyner     if (0 != gpiod_line_request(iv_gpioLine, &iv_gpioConfig, 0))
7773ac368aSBen Tyner     {
789ae5ca41SBen Tyner         std::string logMessage = "failed request for GPIO";
79b1ebfcb1SBen Tyner         trace<level::INFO>(logMessage.c_str());
8073ac368aSBen Tyner     }
8173ac368aSBen Tyner     else
8273ac368aSBen Tyner     {
8373ac368aSBen Tyner         int gpioLineFd;
8473ac368aSBen Tyner 
8573ac368aSBen Tyner         gpioLineFd = gpiod_line_event_get_fd(iv_gpioLine);
8673ac368aSBen Tyner         if (gpioLineFd < 0)
8773ac368aSBen Tyner         {
889ae5ca41SBen Tyner             std::string logMessage = "failed to get file descriptor";
89b1ebfcb1SBen Tyner             trace<level::INFO>(logMessage.c_str());
9073ac368aSBen Tyner         }
9173ac368aSBen Tyner         else
9273ac368aSBen Tyner         {
9373ac368aSBen Tyner             // Register file descriptor for monitoring
9473ac368aSBen Tyner             iv_gpioEventDescriptor.assign(gpioLineFd);
9573ac368aSBen Tyner 
9673ac368aSBen Tyner             // Start monitoring
9773ac368aSBen Tyner             scheduleGPIOEvent();
9873ac368aSBen Tyner         }
9973ac368aSBen Tyner     }
10073ac368aSBen Tyner }
10173ac368aSBen Tyner 
10273ac368aSBen Tyner } // namespace attn
103