Create a custom power button handler
IBM has specific requirements on how the power button must behave, which
are different than what the button handler currently does.
These requirements are:
If power is off:
- A button press will power on as long as the BMC is
in the ready state.
If power is on:
- A button press less than 4s won't do anything.
- At 4s, issue a host power off and start a 10s timer.
- If the button is released within that 10s and not pressed
again, continue with the host power off.
- If the button is released within that 10s and also
pressed again in that 10s, do a hard power (chassis)
off.
- If the button is pressed throughout that 10s
issue a hard power off.
Instead of trying to integrate this behavior into the main button
handler code using even more #ifdefs in various spots, this commit
creates the concept of custom power button handlers, and then implements
one. This makes it less likely it could subtly break when changes are
made to the default code.
A 'power-button-handler' meson option is used to select the handler,
where the default uses the current behavior. A
PowerButtonHandlerFactory then creates the appropriate instance of the
handler selected by that option. If a handler is found, then the
default matches/callbacks won't be done and the handler can deal with
them as it sees fit.
Handlers are derived from a PowerButtonHandler abstract base class that
has 2 pure virtual functions:
- void pressed();
- void released(uint64_t pressTimeMS);
It will register for the power button pressed/released signals and then
call these overridden functions appropriately.
This new handler is implemented in a HostThenChassisPowerOff class.
Change-Id: I3a1df688c4393b4643d42e91c075379f9a266eef
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
diff --git a/inc/power_button_profile.hpp b/inc/power_button_profile.hpp
new file mode 100644
index 0000000..37bfbe6
--- /dev/null
+++ b/inc/power_button_profile.hpp
@@ -0,0 +1,72 @@
+#pragma once
+
+#include "config.h"
+
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/bus/match.hpp>
+#include <sdbusplus/message.hpp>
+
+#include <string>
+
+namespace phosphor::button
+{
+
+constexpr auto powerButtonInterface =
+ "xyz.openbmc_project.Chassis.Buttons.Power";
+namespace sdbusRule = sdbusplus::bus::match::rules;
+
+/**
+ * @class PowerButtonProfile
+ *
+ * Abstract base class for custom power button profiles.
+ *
+ * Calls a derived class's pressed() and released()
+ * functions when the power button is pressed and
+ * released.
+ */
+class PowerButtonProfile
+{
+ public:
+ PowerButtonProfile(sdbusplus::bus_t& bus) :
+ bus(bus),
+ pressedMatch(bus,
+ sdbusRule::type::signal() + sdbusRule::member("Pressed") +
+ sdbusRule::path(POWER_DBUS_OBJECT_NAME) +
+ sdbusRule::interface(powerButtonInterface),
+ std::bind(&PowerButtonProfile::pressedHandler, this,
+ std::placeholders::_1)),
+ releasedMatch(bus,
+ sdbusRule::type::signal() +
+ sdbusRule::member("Released") +
+ sdbusRule::path(POWER_DBUS_OBJECT_NAME) +
+ sdbusRule::interface(powerButtonInterface),
+ std::bind(&PowerButtonProfile::releasedHandler, this,
+ std::placeholders::_1))
+ {}
+
+ virtual ~PowerButtonProfile() = default;
+
+ void pressedHandler(sdbusplus::message_t /* msg*/)
+ {
+ pressed();
+ }
+
+ void releasedHandler(sdbusplus::message_t msg)
+ {
+ auto time = msg.unpack<uint64_t>();
+ released(time);
+ }
+
+ virtual void pressed() = 0;
+
+ virtual void released(uint64_t pressTimeMS) = 0;
+
+ protected:
+ sdbusplus::bus_t& bus;
+
+ private:
+ sdbusplus::bus::match_t pressedMatch;
+ sdbusplus::bus::match_t releasedMatch;
+};
+
+} // namespace phosphor::button