blob: f34bda360d3ef4086a99b77ac992bb4db0de077f [file] [log] [blame]
// 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_t& 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_t& Bus;
ACPIPowerState(sdbusplus::bus_t& 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;
}