blob: 0b5bbd904bf5ffd83cc2f5b75cb55e1d9d730625 [file] [log] [blame]
Vijay Khemka939a6432019-10-09 17:45:45 -07001/**
2 * Copyright © 2019 Facebook
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "gpioMon.hpp"
18
19#include <phosphor-logging/log.hpp>
20#include <sdbusplus/bus.hpp>
21
22namespace phosphor
23{
24namespace gpio
25{
26
27/* systemd service to kick start a target. */
28constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
29constexpr auto SYSTEMD_ROOT = "/org/freedesktop/systemd1";
30constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
31
Delphine CC Chiua66ac0f2023-01-09 17:12:23 +080032constexpr auto falling = "FALLING";
33constexpr auto rising = "RISING";
34
Vijay Khemka939a6432019-10-09 17:45:45 -070035using namespace phosphor::logging;
36
37void GpioMonitor::scheduleEventHandler()
38{
Vijay Khemka939a6432019-10-09 17:45:45 -070039 gpioEventDescriptor.async_wait(
40 boost::asio::posix::stream_descriptor::wait_read,
41 [this](const boost::system::error_code& ec) {
Patrick Williams39084b42023-05-10 07:50:58 -050042 if (ec)
43 {
44 std::string msg = gpioLineMsg + "event handler error" +
45 std::string(ec.message());
46 log<level::ERR>(msg.c_str());
47 return;
48 }
49 gpioEventHandler();
Vijay Khemka939a6432019-10-09 17:45:45 -070050 });
51}
52
53void GpioMonitor::gpioEventHandler()
54{
55 gpiod_line_event gpioLineEvent;
56
57 if (gpiod_line_event_read_fd(gpioEventDescriptor.native_handle(),
58 &gpioLineEvent) < 0)
59 {
60 log<level::ERR>("Failed to read gpioLineEvent from fd",
61 entry("GPIO_LINE=%s", gpioLineMsg.c_str()));
62 return;
63 }
64
65 std::string logMessage =
66 gpioLineMsg + (gpioLineEvent.event_type == GPIOD_LINE_EVENT_RISING_EDGE
67 ? " Asserted"
68 : " Deasserted");
69
70 log<level::INFO>(logMessage.c_str());
71
72 /* Execute the target if it is defined. */
73 if (!target.empty())
74 {
75 auto bus = sdbusplus::bus::new_default();
76 auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
77 SYSTEMD_INTERFACE, "StartUnit");
78 method.append(target);
79 method.append("replace");
80
81 bus.call_noreply(method);
82 }
83
Delphine CC Chiua66ac0f2023-01-09 17:12:23 +080084 std::vector<std::string> targetsToStart;
85 if (gpioLineEvent.event_type == GPIOD_LINE_EVENT_RISING_EDGE)
86 {
87 auto risingFind = targets.find(rising);
88 if (risingFind != targets.end())
89 {
90 targetsToStart = risingFind->second;
91 }
92 }
93 else
94 {
95 auto fallingFind = targets.find(falling);
96 if (fallingFind != targets.end())
97 {
98 targetsToStart = fallingFind->second;
99 }
100 }
101
102 /* Execute the multi targets if it is defined. */
103 if (!targetsToStart.empty())
104 {
105 auto bus = sdbusplus::bus::new_default();
106 for (auto& tar : targetsToStart)
107 {
108 auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
109 SYSTEMD_INTERFACE, "StartUnit");
110 method.append(tar, "replace");
111 bus.call_noreply(method);
112 }
113 }
114
Vijay Khemka939a6432019-10-09 17:45:45 -0700115 /* if not required to continue monitoring then return */
116 if (!continueAfterEvent)
117 {
118 return;
119 }
120
121 /* Schedule a wait event */
122 scheduleEventHandler();
123}
124
125int GpioMonitor::requestGPIOEvents()
126{
Vijay Khemka939a6432019-10-09 17:45:45 -0700127 /* Request an event to monitor for respected gpio line */
128 if (gpiod_line_request(gpioLine, &gpioConfig, 0) < 0)
129 {
130 log<level::ERR>("Failed to request gpioLineEvent",
131 entry("GPIO_LINE=%s", gpioLineMsg.c_str()));
132 return -1;
133 }
134
135 int gpioLineFd = gpiod_line_event_get_fd(gpioLine);
136 if (gpioLineFd < 0)
137 {
138 log<level::ERR>("Failed to get fd for gpioLineEvent",
139 entry("GPIO_LINE=%s", gpioLineMsg.c_str()));
140 return -1;
141 }
142
143 std::string logMsg = gpioLineMsg + " monitoring started";
144 log<level::INFO>(logMsg.c_str());
145
146 /* Assign line fd to descriptor for monitoring */
147 gpioEventDescriptor.assign(gpioLineFd);
148
149 /* Schedule a wait event */
150 scheduleEventHandler();
151
152 return 0;
153}
154} // namespace gpio
155} // namespace phosphor