1* // Copyright 2021 Google LLC 2* // 3* // Licensed under the Apache License, Version 2.0 (the "License"); 4* // you may not use this file except in compliance with the License. 5* // You may obtain a copy of the License at 6* // 7* // http://www.apache.org/licenses/LICENSE-2.0 8* // 9* // Unless required by applicable law or agreed to in writing, software 10* // distributed under the License is distributed on an "AS IS" BASIS, 11* // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12* // See the License for the specific language governing permissions and 13* // limitations under the License. 14* 15* /* 16* * Based off of sdbusplus:/example/calculator-server.cpp 17* */ 18* #include <sdbusplus/bus.hpp> 19* #include <sdbusplus/server.hpp> 20* #include <xyz/openbmc_project/Control/Power/ACPIPowerState/server.hpp> 21* 22* #include <exception> 23* #include <iostream> 24* #include <optional> 25* #include <string> 26* 27* constexpr auto hostS5Unit = "host-s5-state.target"; 28* constexpr auto hostS0Unit = "host-s0-state.target"; 29* 30* constexpr auto systemdBusName = "org.freedesktop.systemd1"; 31* constexpr auto systemdPath = "/org/freedesktop/systemd1"; 32* constexpr auto systemdInterface = "org.freedesktop.systemd1.Manager"; 33* 34* constexpr auto acpiObjPath = 35* "/xyz/openbmc_project/control/host0/acpi_power_state"; 36* constexpr auto acpiInterface = 37* "xyz.openbmc_project.Control.Power.ACPIPowerState"; 38* 39* using ACPIPowerStateInherit = sdbusplus::server::object_t< 40* sdbusplus::xyz::openbmc_project::Control::Power::server::ACPIPowerState>; 41* 42* // Pulled and modified from arcadia-leds/poll_gpio.cpp 43* static void startSystemdUnit(sdbusplus::bus::bus& bus, const std::string& unit) 44* { 45* auto method = bus.new_method_call(systemdBusName, systemdPath, 46* systemdInterface, "StartUnit"); 47* method.append(unit, "replace"); 48* bus.call(method); 49* } 50* 51* struct ACPIPowerState : ACPIPowerStateInherit 52* { 53* // Keep track of the bus for starting/stopping systemd units 54* sdbusplus::bus::bus& Bus; 55* 56* ACPIPowerState(sdbusplus::bus::bus& bus, const char* path) : 57* ACPIPowerStateInherit(bus, path), Bus(bus) 58* {} 59* 60* ACPI sysACPIStatus(ACPI value) 61* { 62* std::cout << "State change " 63* << ACPIPowerStateInherit::convertACPIToString(value) 64* << std::endl; 65* 66* switch (value) 67* { 68* case ACPI::S5_G2: 69* std::cout << "Entered S5" << std::endl; 70* startSystemdUnit(Bus, hostS5Unit); 71* break; 72* case ACPI::S0_G0_D0: 73* std::cout << "Entered S0" << std::endl; 74* startSystemdUnit(Bus, hostS0Unit); 75* break; 76* default: 77* break; 78* } 79* 80* return ACPIPowerStateInherit::sysACPIStatus(value); 81* } 82* }; 83* 84* int main() 85* { 86* 87* auto b = sdbusplus::bus::new_default(); 88* sdbusplus::server::manager_t m{b, acpiObjPath}; 89* 90* // Reserve the dbus service for ACPI Power state changes coming from the 91* // BIOS 92* b.request_name(acpiInterface); 93* 94* ACPIPowerState aps{b, acpiObjPath}; 95* 96* // Handle dbus processing forever. 97* for (;;) 98* { 99* b.process_discard(); // discard any unhandled messages 100* b.wait(); 101* } 102* 103* return 1; 104* } 105*