acpi-power-state: Import from gBMC

Imported from the scripts repo

Google-Bug-Id: 182214245
Upstream: d416a695e0747be61d13cb1f1ddba9de2c10238a
Signed-off-by: Brandon Kim <brandonkim@google.com>
Change-Id: Ib302ea4b6fb52f5579fcb91d00fd12705edc04d1
diff --git a/acpi-power-state-daemon/acpi_power_state.cpp b/acpi-power-state-daemon/acpi_power_state.cpp
new file mode 100644
index 0000000..9b5d5d2
--- /dev/null
+++ b/acpi-power-state-daemon/acpi_power_state.cpp
@@ -0,0 +1,104 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/*
+ * Based off of sdbusplus:/example/calculator-server.cpp
+ */
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/server.hpp>
+#include <xyz/openbmc_project/Control/Power/ACPIPowerState/server.hpp>
+
+#include <exception>
+#include <iostream>
+#include <optional>
+#include <string>
+
+constexpr auto hostS5Unit = "host-s5-state.target";
+constexpr auto hostS0Unit = "host-s0-state.target";
+
+constexpr auto systemdBusName = "org.freedesktop.systemd1";
+constexpr auto systemdPath = "/org/freedesktop/systemd1";
+constexpr auto systemdInterface = "org.freedesktop.systemd1.Manager";
+
+constexpr auto acpiObjPath =
+    "/xyz/openbmc_project/control/host0/acpi_power_state";
+constexpr auto acpiInterface =
+    "xyz.openbmc_project.Control.Power.ACPIPowerState";
+
+using ACPIPowerStateInherit = sdbusplus::server::object_t<
+    sdbusplus::xyz::openbmc_project::Control::Power::server::ACPIPowerState>;
+
+// Pulled and modified from arcadia-leds/poll_gpio.cpp
+static void startSystemdUnit(sdbusplus::bus::bus& bus, const std::string& unit)
+{
+    auto method = bus.new_method_call(systemdBusName, systemdPath,
+                                      systemdInterface, "StartUnit");
+    method.append(unit, "replace");
+    bus.call(method);
+}
+
+struct ACPIPowerState : ACPIPowerStateInherit
+{
+    // Keep track of the bus for starting/stopping systemd units
+    sdbusplus::bus::bus& Bus;
+
+    ACPIPowerState(sdbusplus::bus::bus& bus, const char* path) :
+        ACPIPowerStateInherit(bus, path), Bus(bus)
+    {}
+
+    ACPI sysACPIStatus(ACPI value)
+    {
+        std::cout << "State change "
+                  << ACPIPowerStateInherit::convertACPIToString(value)
+                  << std::endl;
+
+        switch (value)
+        {
+            case ACPI::S5_G2:
+                std::cout << "Entered S5" << std::endl;
+                startSystemdUnit(Bus, hostS5Unit);
+                break;
+            case ACPI::S0_G0_D0:
+                std::cout << "Entered S0" << std::endl;
+                startSystemdUnit(Bus, hostS0Unit);
+                break;
+            default:
+                break;
+        }
+
+        return ACPIPowerStateInherit::sysACPIStatus(value);
+    }
+};
+
+int main()
+{
+
+    auto b = sdbusplus::bus::new_default();
+    sdbusplus::server::manager_t m{b, acpiObjPath};
+
+    // Reserve the dbus service for ACPI Power state changes coming from the
+    // BIOS
+    b.request_name(acpiInterface);
+
+    ACPIPowerState aps{b, acpiObjPath};
+
+    // Handle dbus processing forever.
+    for (;;)
+    {
+        b.process_discard(); // discard any unhandled messages
+        b.wait();
+    }
+
+    return 1;
+}