1 #include "attn_monitor.hpp"
2 
3 #include "attn_handler.hpp"
4 
5 #include <logging.hpp>
6 
7 namespace attn
8 {
9 
10 /** @brief Register a callback for gpio event */
11 void AttnMonitor::scheduleGPIOEvent()
12 {
13     std::string logMessage = "... waiting for events ...";
14     log<level::INFO>(logMessage.c_str());
15 
16     // Register async callback, note that callback is a
17     // lambda function with "this" pointer captured
18     iv_gpioEventDescriptor.async_wait(
19         boost::asio::posix::stream_descriptor::wait_read,
20         [this](const boost::system::error_code& ec) {
21             if (ec)
22             {
23                 std::string logMessage =
24                     "GPIO Async wait error: " + std::string(ec.message());
25                 log<level::INFO>(logMessage.c_str());
26             }
27             else
28             {
29                 handleGPIOEvent(); // gpio trigger detected
30             }
31             return;
32         }); // register async callback
33 }
34 
35 /** @brief Handle the GPIO state change event */
36 void AttnMonitor::handleGPIOEvent()
37 {
38     gpiod_line_event gpioEvent;
39     std::string logMessage;
40 
41     if (gpiod_line_event_read_fd(iv_gpioEventDescriptor.native_handle(),
42                                  &gpioEvent) < 0)
43     {
44         logMessage = "GPIO line read failed";
45         log<level::INFO>(logMessage.c_str());
46     }
47     else
48     {
49         switch (gpiod_line_get_value(iv_gpioLine))
50         {
51             // active attention when gpio == 0
52             case 0:
53                 attnHandler(iv_breakpoints);
54                 break;
55 
56             // gpio == 1, GPIO handler should not be executing
57             case 1:
58                 logMessage = "GPIO handler out of sync";
59                 log<level::INFO>(logMessage.c_str());
60                 break;
61 
62             // unexpected value
63             default:
64                 logMessage = "GPIO line unexpected value";
65                 log<level::INFO>(logMessage.c_str());
66         }
67     }
68     scheduleGPIOEvent(); // continue monitoring gpio
69 }
70 
71 /** @brief Request a GPIO line for monitoring attention events */
72 void AttnMonitor::requestGPIOEvent()
73 {
74     if (0 != gpiod_line_request(iv_gpioLine, &iv_gpioConfig, 0))
75     {
76         std::string logMessage = "failed request for GPIO";
77         log<level::INFO>(logMessage.c_str());
78     }
79     else
80     {
81         int gpioLineFd;
82 
83         gpioLineFd = gpiod_line_event_get_fd(iv_gpioLine);
84         if (gpioLineFd < 0)
85         {
86             std::string logMessage = "failed to get file descriptor";
87             log<level::INFO>(logMessage.c_str());
88         }
89         else
90         {
91             // Register file descriptor for monitoring
92             iv_gpioEventDescriptor.assign(gpioLineFd);
93 
94             // Start monitoring
95             scheduleGPIOEvent();
96         }
97     }
98 }
99 
100 } // namespace attn
101