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