1 #include <attn_handler.hpp>
2 #include <attn_logging.hpp>
3 #include <attn_monitor.hpp>
4 
5 namespace attn
6 {
7 
8 /** @brief Register a callback for gpio event */
9 void AttnMonitor::scheduleGPIOEvent()
10 {
11     std::string logMessage = "... waiting for events ...";
12     trace<level::INFO>(logMessage.c_str());
13 
14     // Register async callback, note that callback is a
15     // lambda function with "this" pointer captured
16     iv_gpioEventDescriptor.async_wait(
17         boost::asio::posix::stream_descriptor::wait_read,
18         [this](const boost::system::error_code& ec) {
19             if (ec)
20             {
21                 std::string logMessage =
22                     "GPIO Async wait error: " + std::string(ec.message());
23                 trace<level::INFO>(logMessage.c_str());
24             }
25             else
26             {
27                 trace<level::INFO>(
28                     "Attention monitor detected active attention");
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         trace<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                 logMessage = "Attention monitor calling attention handler";
54                 trace<level::INFO>(logMessage.c_str());
55                 attnHandler(iv_config);
56                 break;
57 
58             // gpio == 1, GPIO handler should not be executing
59             case 1:
60                 logMessage = "GPIO handler out of sync";
61                 trace<level::INFO>(logMessage.c_str());
62                 break;
63 
64             // unexpected value
65             default:
66                 logMessage = "GPIO line unexpected value";
67                 trace<level::INFO>(logMessage.c_str());
68         }
69     }
70     scheduleGPIOEvent(); // continue monitoring gpio
71 }
72 
73 /** @brief Request a GPIO line for monitoring attention events */
74 void AttnMonitor::requestGPIOEvent()
75 {
76     if (0 != gpiod_line_request(iv_gpioLine, &iv_gpioConfig, 0))
77     {
78         std::string logMessage = "failed request for GPIO";
79         trace<level::INFO>(logMessage.c_str());
80     }
81     else
82     {
83         int gpioLineFd;
84 
85         gpioLineFd = gpiod_line_event_get_fd(iv_gpioLine);
86         if (gpioLineFd < 0)
87         {
88             std::string logMessage = "failed to get file descriptor";
89             trace<level::INFO>(logMessage.c_str());
90         }
91         else
92         {
93             // Register file descriptor for monitoring
94             iv_gpioEventDescriptor.assign(gpioLineFd);
95 
96             // Start monitoring
97             scheduleGPIOEvent();
98         }
99     }
100 }
101 
102 } // namespace attn
103