blob: 2ab079aab970615a2743c3d641a98ec666d9962d [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
32using namespace phosphor::logging;
33
34void GpioMonitor::scheduleEventHandler()
35{
36
37 gpioEventDescriptor.async_wait(
38 boost::asio::posix::stream_descriptor::wait_read,
39 [this](const boost::system::error_code& ec) {
40 if (ec)
41 {
42 std::string msg = gpioLineMsg + "event handler error" +
43 std::string(ec.message());
44 log<level::ERR>(msg.c_str());
45 return;
46 }
47 gpioEventHandler();
48 });
49}
50
51void GpioMonitor::gpioEventHandler()
52{
53 gpiod_line_event gpioLineEvent;
54
55 if (gpiod_line_event_read_fd(gpioEventDescriptor.native_handle(),
56 &gpioLineEvent) < 0)
57 {
58 log<level::ERR>("Failed to read gpioLineEvent from fd",
59 entry("GPIO_LINE=%s", gpioLineMsg.c_str()));
60 return;
61 }
62
63 std::string logMessage =
64 gpioLineMsg + (gpioLineEvent.event_type == GPIOD_LINE_EVENT_RISING_EDGE
65 ? " Asserted"
66 : " Deasserted");
67
68 log<level::INFO>(logMessage.c_str());
69
70 /* Execute the target if it is defined. */
71 if (!target.empty())
72 {
73 auto bus = sdbusplus::bus::new_default();
74 auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
75 SYSTEMD_INTERFACE, "StartUnit");
76 method.append(target);
77 method.append("replace");
78
79 bus.call_noreply(method);
80 }
81
82 /* if not required to continue monitoring then return */
83 if (!continueAfterEvent)
84 {
85 return;
86 }
87
88 /* Schedule a wait event */
89 scheduleEventHandler();
90}
91
92int GpioMonitor::requestGPIOEvents()
93{
94
95 /* Request an event to monitor for respected gpio line */
96 if (gpiod_line_request(gpioLine, &gpioConfig, 0) < 0)
97 {
98 log<level::ERR>("Failed to request gpioLineEvent",
99 entry("GPIO_LINE=%s", gpioLineMsg.c_str()));
100 return -1;
101 }
102
103 int gpioLineFd = gpiod_line_event_get_fd(gpioLine);
104 if (gpioLineFd < 0)
105 {
106 log<level::ERR>("Failed to get fd for gpioLineEvent",
107 entry("GPIO_LINE=%s", gpioLineMsg.c_str()));
108 return -1;
109 }
110
111 std::string logMsg = gpioLineMsg + " monitoring started";
112 log<level::INFO>(logMsg.c_str());
113
114 /* Assign line fd to descriptor for monitoring */
115 gpioEventDescriptor.assign(gpioLineFd);
116
117 /* Schedule a wait event */
118 scheduleEventHandler();
119
120 return 0;
121}
122} // namespace gpio
123} // namespace phosphor