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