1b797b3e1SBen Tyner #include <attn/attn_handler.hpp>
2b797b3e1SBen Tyner #include <attn/attn_monitor.hpp>
3*bfa831a8Saustinfcui #include <util/trace.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 {
1173ac368aSBen Tyner     // Register async callback, note that callback is a
1273ac368aSBen Tyner     // lambda function with "this" pointer captured
1373ac368aSBen Tyner     iv_gpioEventDescriptor.async_wait(
1473ac368aSBen Tyner         boost::asio::posix::stream_descriptor::wait_read,
1573ac368aSBen Tyner         [this](const boost::system::error_code& ec) {
1673ac368aSBen Tyner             if (ec)
1773ac368aSBen Tyner             {
18*bfa831a8Saustinfcui                 trace::err("GPIO Async wait error: %s", ec.message().c_str());
1973ac368aSBen Tyner             }
2073ac368aSBen Tyner             else
2173ac368aSBen Tyner             {
22*bfa831a8Saustinfcui                 trace::inf("Attention GPIO active");
2373ac368aSBen Tyner                 handleGPIOEvent(); // gpio trigger detected
2473ac368aSBen Tyner             }
2573ac368aSBen Tyner             return;
2673ac368aSBen Tyner         }); // register async callback
2773ac368aSBen Tyner }
2873ac368aSBen Tyner 
2973ac368aSBen Tyner /** @brief Handle the GPIO state change event */
3073ac368aSBen Tyner void AttnMonitor::handleGPIOEvent()
3173ac368aSBen Tyner {
3273ac368aSBen Tyner     gpiod_line_event gpioEvent;
3373ac368aSBen Tyner     std::string logMessage;
3473ac368aSBen Tyner 
3573ac368aSBen Tyner     if (gpiod_line_event_read_fd(iv_gpioEventDescriptor.native_handle(),
3673ac368aSBen Tyner                                  &gpioEvent) < 0)
3773ac368aSBen Tyner     {
38*bfa831a8Saustinfcui         trace::err("GPIO line read failed");
3973ac368aSBen Tyner     }
4073ac368aSBen Tyner     else
4173ac368aSBen Tyner     {
4273ac368aSBen Tyner         switch (gpiod_line_get_value(iv_gpioLine))
4373ac368aSBen Tyner         {
4473ac368aSBen Tyner             // active attention when gpio == 0
4573ac368aSBen Tyner             case 0:
463fb52e53SBen Tyner                 attnHandler(iv_config);
4773ac368aSBen Tyner                 break;
4873ac368aSBen Tyner 
4973ac368aSBen Tyner             // gpio == 1, GPIO handler should not be executing
5073ac368aSBen Tyner             case 1:
51*bfa831a8Saustinfcui                 trace::inf("GPIO handler out of sync");
5273ac368aSBen Tyner                 break;
5373ac368aSBen Tyner 
5473ac368aSBen Tyner             // unexpected value
5573ac368aSBen Tyner             default:
56*bfa831a8Saustinfcui                 trace::inf("GPIO line unexpected value");
5773ac368aSBen Tyner         }
5873ac368aSBen Tyner     }
5973ac368aSBen Tyner     scheduleGPIOEvent(); // continue monitoring gpio
6073ac368aSBen Tyner }
6173ac368aSBen Tyner 
6273ac368aSBen Tyner /** @brief Request a GPIO line for monitoring attention events */
6373ac368aSBen Tyner void AttnMonitor::requestGPIOEvent()
6473ac368aSBen Tyner {
6573ac368aSBen Tyner     if (0 != gpiod_line_request(iv_gpioLine, &iv_gpioConfig, 0))
6673ac368aSBen Tyner     {
67*bfa831a8Saustinfcui         trace::err("failed request for GPIO");
6873ac368aSBen Tyner     }
6973ac368aSBen Tyner     else
7073ac368aSBen Tyner     {
7173ac368aSBen Tyner         int gpioLineFd;
7273ac368aSBen Tyner 
7373ac368aSBen Tyner         gpioLineFd = gpiod_line_event_get_fd(iv_gpioLine);
7473ac368aSBen Tyner         if (gpioLineFd < 0)
7573ac368aSBen Tyner         {
76*bfa831a8Saustinfcui             trace::err("failed to get file descriptor");
7773ac368aSBen Tyner         }
7873ac368aSBen Tyner         else
7973ac368aSBen Tyner         {
8073ac368aSBen Tyner             // Register file descriptor for monitoring
8173ac368aSBen Tyner             iv_gpioEventDescriptor.assign(gpioLineFd);
8273ac368aSBen Tyner 
8373ac368aSBen Tyner             // Start monitoring
8473ac368aSBen Tyner             scheduleGPIOEvent();
8573ac368aSBen Tyner         }
8673ac368aSBen Tyner     }
8773ac368aSBen Tyner }
8873ac368aSBen Tyner 
8973ac368aSBen Tyner } // namespace attn
90