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