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