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