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