blob: deebebec3f1012a9ae37325fd6b4424d4ac69b78 [file] [log] [blame]
Christopher Meis75ff1672025-09-23 11:40:06 +02001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
Vijay Khemka939a6432019-10-09 17:45:45 -07003
4#include "gpioMon.hpp"
5
George Liu2a8848c2023-08-01 13:49:28 +08006#include <phosphor-logging/lg2.hpp>
Vijay Khemka939a6432019-10-09 17:45:45 -07007#include <sdbusplus/bus.hpp>
8
9namespace phosphor
10{
11namespace gpio
12{
13
14/* systemd service to kick start a target. */
15constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
16constexpr auto SYSTEMD_ROOT = "/org/freedesktop/systemd1";
17constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
18
Delphine CC Chiua66ac0f2023-01-09 17:12:23 +080019constexpr auto falling = "FALLING";
20constexpr auto rising = "RISING";
Amithash Prasadba917cf2025-04-21 14:52:43 -070021constexpr auto init_high = "INIT_HIGH";
22constexpr auto init_low = "INIT_LOW";
Delphine CC Chiua66ac0f2023-01-09 17:12:23 +080023
Vijay Khemka939a6432019-10-09 17:45:45 -070024void GpioMonitor::scheduleEventHandler()
25{
Vijay Khemka939a6432019-10-09 17:45:45 -070026 gpioEventDescriptor.async_wait(
27 boost::asio::posix::stream_descriptor::wait_read,
28 [this](const boost::system::error_code& ec) {
Patrick Williams8377d592024-08-16 15:21:08 -040029 if (ec)
30 {
31 lg2::error("{GPIO} event handler error: {ERROR}", "GPIO",
32 gpioLineMsg, "ERROR", ec.message());
33 return;
34 }
35 gpioEventHandler();
36 });
Vijay Khemka939a6432019-10-09 17:45:45 -070037}
38
39void GpioMonitor::gpioEventHandler()
40{
41 gpiod_line_event gpioLineEvent;
42
43 if (gpiod_line_event_read_fd(gpioEventDescriptor.native_handle(),
44 &gpioLineEvent) < 0)
45 {
George Liu2a8848c2023-08-01 13:49:28 +080046 lg2::error("Failed to read {GPIO} from fd", "GPIO", gpioLineMsg);
Vijay Khemka939a6432019-10-09 17:45:45 -070047 return;
48 }
49
George Liu2a8848c2023-08-01 13:49:28 +080050 if (gpioLineEvent.event_type == GPIOD_LINE_EVENT_RISING_EDGE)
51 {
52 lg2::info("{GPIO} Asserted", "GPIO", gpioLineMsg);
53 }
54 else
55 {
56 lg2::info("{GPIO} Deasserted", "GPIO", gpioLineMsg);
57 }
Vijay Khemka939a6432019-10-09 17:45:45 -070058
59 /* Execute the target if it is defined. */
60 if (!target.empty())
61 {
62 auto bus = sdbusplus::bus::new_default();
63 auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
64 SYSTEMD_INTERFACE, "StartUnit");
65 method.append(target);
66 method.append("replace");
67
68 bus.call_noreply(method);
69 }
70
Delphine CC Chiua66ac0f2023-01-09 17:12:23 +080071 std::vector<std::string> targetsToStart;
72 if (gpioLineEvent.event_type == GPIOD_LINE_EVENT_RISING_EDGE)
73 {
74 auto risingFind = targets.find(rising);
75 if (risingFind != targets.end())
76 {
77 targetsToStart = risingFind->second;
78 }
79 }
80 else
81 {
82 auto fallingFind = targets.find(falling);
83 if (fallingFind != targets.end())
84 {
85 targetsToStart = fallingFind->second;
86 }
87 }
88
89 /* Execute the multi targets if it is defined. */
90 if (!targetsToStart.empty())
91 {
92 auto bus = sdbusplus::bus::new_default();
93 for (auto& tar : targetsToStart)
94 {
95 auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
96 SYSTEMD_INTERFACE, "StartUnit");
97 method.append(tar, "replace");
98 bus.call_noreply(method);
99 }
100 }
101
Vijay Khemka939a6432019-10-09 17:45:45 -0700102 /* if not required to continue monitoring then return */
103 if (!continueAfterEvent)
104 {
105 return;
106 }
107
108 /* Schedule a wait event */
109 scheduleEventHandler();
110}
111
Amithash Prasadba917cf2025-04-21 14:52:43 -0700112void GpioMonitor::gpioHandleInitialState(bool value)
113{
114 if (auto itr = targets.find(value ? init_high : init_low);
115 itr != targets.end())
116 {
117 auto bus = sdbusplus::bus::new_default();
118 for (const auto& tar : itr->second)
119 {
120 auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
121 SYSTEMD_INTERFACE, "StartUnit");
122 method.append(tar, "replace");
123 bus.call_noreply(method);
124 }
125 }
126}
127
Vijay Khemka939a6432019-10-09 17:45:45 -0700128int GpioMonitor::requestGPIOEvents()
129{
Vijay Khemka939a6432019-10-09 17:45:45 -0700130 /* Request an event to monitor for respected gpio line */
131 if (gpiod_line_request(gpioLine, &gpioConfig, 0) < 0)
132 {
George Liu2a8848c2023-08-01 13:49:28 +0800133 lg2::error("Failed to request {GPIO}", "GPIO", gpioLineMsg);
Vijay Khemka939a6432019-10-09 17:45:45 -0700134 return -1;
135 }
136
137 int gpioLineFd = gpiod_line_event_get_fd(gpioLine);
138 if (gpioLineFd < 0)
139 {
George Liu2a8848c2023-08-01 13:49:28 +0800140 lg2::error("Failed to get fd for {GPIO}", "GPIO", gpioLineMsg);
Vijay Khemka939a6432019-10-09 17:45:45 -0700141 return -1;
142 }
143
Amithash Prasadba917cf2025-04-21 14:52:43 -0700144 int value = gpiod_line_get_value(gpioLine);
145 if (value < 0)
146 {
147 lg2::error("Failed to get value for {GPIO} Error: {ERROR}", "GPIO",
148 gpioLineMsg, "ERROR", strerror(errno));
149 }
150 else
151 {
152 gpioHandleInitialState(value != 0);
153 }
154
George Liu2a8848c2023-08-01 13:49:28 +0800155 lg2::info("{GPIO} monitoring started", "GPIO", gpioLineMsg);
Vijay Khemka939a6432019-10-09 17:45:45 -0700156
157 /* Assign line fd to descriptor for monitoring */
158 gpioEventDescriptor.assign(gpioLineFd);
159
160 /* Schedule a wait event */
161 scheduleEventHandler();
162
163 return 0;
164}
165} // namespace gpio
166} // namespace phosphor