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