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
startSystemdUnit(sdbusplus::bus_t & bus,const std::string & unit)43* static void startSystemdUnit(sdbusplus::bus_t& 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_t& Bus;
55*
ACPIPowerStateACPIPowerState56* ACPIPowerState(sdbusplus::bus_t& bus, const char* path) :
57* ACPIPowerStateInherit(bus, path), Bus(bus)
58* {}
59*
sysACPIStatusACPIPowerState60* 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*
main()84* int main()
85* {
86* auto b = sdbusplus::bus::new_default();
87* sdbusplus::server::manager_t m{b, acpiObjPath};
88*
89* // Reserve the dbus service for ACPI Power state changes coming from the
90* // BIOS
91* b.request_name(acpiInterface);
92*
93* ACPIPowerState aps{b, acpiObjPath};
94*
95* // Handle dbus processing forever.
96* for (;;)
97* {
98* b.process_discard(); // discard any unhandled messages
99* b.wait();
100* }
101*
102* return 1;
103* }
104*