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 */
scheduleGPIOEvent()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 */
handleGPIOEvent()3073ac368aSBen Tyner void AttnMonitor::handleGPIOEvent()
3173ac368aSBen Tyner {
3273ac368aSBen Tyner     gpiod_line_event gpioEvent;
3373ac368aSBen Tyner 
3473ac368aSBen Tyner     if (gpiod_line_event_read_fd(iv_gpioEventDescriptor.native_handle(),
3573ac368aSBen Tyner                                  &gpioEvent) < 0)
3673ac368aSBen Tyner     {
37*bfa831a8Saustinfcui         trace::err("GPIO line read failed");
3873ac368aSBen Tyner     }
3973ac368aSBen Tyner     else
4073ac368aSBen Tyner     {
4173ac368aSBen Tyner         switch (gpiod_line_get_value(iv_gpioLine))
4273ac368aSBen Tyner         {
4373ac368aSBen Tyner             // active attention when gpio == 0
4473ac368aSBen Tyner             case 0:
453fb52e53SBen Tyner                 attnHandler(iv_config);
4673ac368aSBen Tyner                 break;
4773ac368aSBen Tyner 
4873ac368aSBen Tyner             // gpio == 1, GPIO handler should not be executing
4973ac368aSBen Tyner             case 1:
50*bfa831a8Saustinfcui                 trace::inf("GPIO handler out of sync");
5173ac368aSBen Tyner                 break;
5273ac368aSBen Tyner 
5373ac368aSBen Tyner             // unexpected value
5473ac368aSBen Tyner             default:
55*bfa831a8Saustinfcui                 trace::inf("GPIO line unexpected value");
5673ac368aSBen Tyner         }
5773ac368aSBen Tyner     }
5873ac368aSBen Tyner     scheduleGPIOEvent(); // continue monitoring gpio
5973ac368aSBen Tyner }
6073ac368aSBen Tyner 
6173ac368aSBen Tyner /** @brief Request a GPIO line for monitoring attention events */
requestGPIOEvent()6273ac368aSBen Tyner void AttnMonitor::requestGPIOEvent()
6373ac368aSBen Tyner {
6473ac368aSBen Tyner     if (0 != gpiod_line_request(iv_gpioLine, &iv_gpioConfig, 0))
6573ac368aSBen Tyner     {
66*bfa831a8Saustinfcui         trace::err("failed request for GPIO");
6773ac368aSBen Tyner     }
6873ac368aSBen Tyner     else
6973ac368aSBen Tyner     {
7073ac368aSBen Tyner         int gpioLineFd;
7173ac368aSBen Tyner 
7273ac368aSBen Tyner         gpioLineFd = gpiod_line_event_get_fd(iv_gpioLine);
7373ac368aSBen Tyner         if (gpioLineFd < 0)
7473ac368aSBen Tyner         {
75*bfa831a8Saustinfcui             trace::err("failed to get file descriptor");
7673ac368aSBen Tyner         }
7773ac368aSBen Tyner         else
7873ac368aSBen Tyner         {
7973ac368aSBen Tyner             // Register file descriptor for monitoring
8073ac368aSBen Tyner             iv_gpioEventDescriptor.assign(gpioLineFd);
8173ac368aSBen Tyner 
8273ac368aSBen Tyner             // Start monitoring
8373ac368aSBen Tyner             scheduleGPIOEvent();
8473ac368aSBen Tyner         }
8573ac368aSBen Tyner     }
8673ac368aSBen Tyner }
8773ac368aSBen Tyner 
8873ac368aSBen Tyner } // namespace attn
89