xref: /openbmc/google-misc/subprojects/acpi-power-state-daemon/acpi_power_state.cpp (revision 15fe169d1fbdd510bb9cfc9bb725baf0613350ff)
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*