xref: /openbmc/phosphor-gpio-monitor/monitor.cpp (revision dace680fa404d7c02a68db105fd7b958b4681442)
1 /**
2  * Copyright © 2016 IBM Corporation
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 "config.h"
18 
19 #include "monitor.hpp"
20 
21 #include <fcntl.h>
22 
23 #include <phosphor-logging/log.hpp>
24 
25 namespace phosphor
26 {
27 namespace gpio
28 {
29 
30 // systemd service to kick start a target.
31 constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
32 constexpr auto SYSTEMD_ROOT = "/org/freedesktop/systemd1";
33 constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
34 
35 using namespace phosphor::logging;
36 
37 // Callback handler when there is an activity on the FD
38 int Monitor::processEvents(sd_event_source* es, int fd, uint32_t revents,
39                            void* userData)
40 {
41     log<level::INFO>("GPIO line altered");
42     auto monitor = static_cast<Monitor*>(userData);
43 
44     monitor->analyzeEvent();
45     return 0;
46 }
47 
48 // Analyzes the GPIO event
49 void Monitor::analyzeEvent()
50 {
51     // Data returned
52     struct input_event ev
53     {
54     };
55     int rc = 0;
56 
57     // While testing, observed that not having a loop here was leading
58     // into events being missed.
59     while (rc >= 0)
60     {
61         // Wait until no more events are available on the device.
62         rc = libevdev_next_event(devicePtr.get(), LIBEVDEV_READ_FLAG_NORMAL,
63                                  &ev);
64         if (rc < 0)
65         {
66             // There was an error waiting for events, mostly that there are no
67             // events to be read.. So continue waiting...
68             return;
69         };
70 
71         if (rc == LIBEVDEV_READ_STATUS_SUCCESS)
72         {
73             if (ev.type == EV_SYN && ev.code == SYN_REPORT)
74             {
75                 continue;
76             }
77             else if (ev.code == key && ev.value == polarity)
78             {
79                 // If the code/value is what we are interested in, declare done.
80                 // User supplied systemd unit
81                 if (!target.empty())
82                 {
83                     auto bus = sdbusplus::bus::new_default();
84                     auto method =
85                         bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
86                                             SYSTEMD_INTERFACE, "StartUnit");
87                     method.append(target);
88                     method.append("replace");
89 
90                     bus.call_noreply(method);
91                 }
92 
93                 if (!continueAfterKeyPress)
94                 {
95                     // This marks the completion of handling the gpio assertion
96                     // and the app can exit
97                     complete = true;
98                 }
99                 return;
100             }
101         }
102     };
103 
104     return;
105 }
106 
107 } // namespace gpio
108 } // namespace phosphor
109