11a309f77SMatt Spinler #pragma once 21a309f77SMatt Spinler #include "power_button_profile.hpp" 31a309f77SMatt Spinler 41a309f77SMatt Spinler #include <sdbusplus/bus/match.hpp> 51a309f77SMatt Spinler #include <sdeventplus/event.hpp> 61a309f77SMatt Spinler #include <sdeventplus/utility/timer.hpp> 71a309f77SMatt Spinler #include <xyz/openbmc_project/State/Host/server.hpp> 81a309f77SMatt Spinler 91a309f77SMatt Spinler #include <chrono> 101a309f77SMatt Spinler 111a309f77SMatt Spinler namespace phosphor::button 121a309f77SMatt Spinler { 131a309f77SMatt Spinler 141a309f77SMatt Spinler /** 151a309f77SMatt Spinler * @class HostThenChassisPowerOff 161a309f77SMatt Spinler * 171a309f77SMatt Spinler * A custom power button handler that will do the following: 181a309f77SMatt Spinler * 191a309f77SMatt Spinler * If power is off: 201a309f77SMatt Spinler * - A button press will power on as long as the BMC is 211a309f77SMatt Spinler * in the ready state. 221a309f77SMatt Spinler * 231a309f77SMatt Spinler * If power is on: 241a309f77SMatt Spinler * - A button press less than 4s won't do anything. 251a309f77SMatt Spinler * - At 4s, issue a host power off and start a 10s timer. 261a309f77SMatt Spinler * - If the button is released within that 10s and not pressed 271a309f77SMatt Spinler * again, continue with the host power off. 281a309f77SMatt Spinler * - If the button is released within that 10s and also 291a309f77SMatt Spinler * pressed again in that 10s, do a hard power (chassis) 301a309f77SMatt Spinler * off. 311a309f77SMatt Spinler * - If the button is pressed throughout that 10s 321a309f77SMatt Spinler * issue a hard power off. 331a309f77SMatt Spinler */ 341a309f77SMatt Spinler class HostThenChassisPowerOff : public PowerButtonProfile 351a309f77SMatt Spinler { 361a309f77SMatt Spinler public: 371a309f77SMatt Spinler enum class PowerOpState 381a309f77SMatt Spinler { 391a309f77SMatt Spinler powerOnPress, 401a309f77SMatt Spinler buttonNotPressed, 411a309f77SMatt Spinler buttonPressed, 421a309f77SMatt Spinler buttonPressedHostOffStarted, 431a309f77SMatt Spinler buttonReleasedHostToChassisOffWindow, 441a309f77SMatt Spinler chassisOffStarted 451a309f77SMatt Spinler }; 461a309f77SMatt Spinler 471a309f77SMatt Spinler /** 481a309f77SMatt Spinler * @brief Constructor 491a309f77SMatt Spinler * @param[in] bus - The sdbusplus bus object 501a309f77SMatt Spinler */ HostThenChassisPowerOff(sdbusplus::bus_t & bus)511a309f77SMatt Spinler explicit HostThenChassisPowerOff(sdbusplus::bus_t& bus) : 521a309f77SMatt Spinler PowerButtonProfile(bus), state(PowerOpState::buttonNotPressed), 531a309f77SMatt Spinler timer(bus.get_event(), 541a309f77SMatt Spinler std::bind(&HostThenChassisPowerOff::timerHandler, this), 551a309f77SMatt Spinler pollInterval) 561a309f77SMatt Spinler { 571a309f77SMatt Spinler timer.setEnabled(false); 581a309f77SMatt Spinler } 591a309f77SMatt Spinler 601a309f77SMatt Spinler /** 611a309f77SMatt Spinler * @brief Returns the name that matches the value in 621a309f77SMatt Spinler * meson_options.txt. 631a309f77SMatt Spinler */ getName()64*31ce375eSRush Chen static constexpr std::string getName() 651a309f77SMatt Spinler { 661a309f77SMatt Spinler return "host_then_chassis_poweroff"; 671a309f77SMatt Spinler } 681a309f77SMatt Spinler 691a309f77SMatt Spinler HostThenChassisPowerOff() = delete; 701a309f77SMatt Spinler ~HostThenChassisPowerOff() = default; 711a309f77SMatt Spinler 721a309f77SMatt Spinler /** 731a309f77SMatt Spinler * @brief Called when the power button is pressed. 741a309f77SMatt Spinler */ 751a309f77SMatt Spinler virtual void pressed() override; 761a309f77SMatt Spinler 771a309f77SMatt Spinler /** 781a309f77SMatt Spinler * @brief Called when the power button is released. 791a309f77SMatt Spinler * 801a309f77SMatt Spinler * @param[in] pressTimeMS - How long the button was pressed 811a309f77SMatt Spinler * in milliseconds. 821a309f77SMatt Spinler */ 831a309f77SMatt Spinler virtual void released(uint64_t pressTimeMS) override; 841a309f77SMatt Spinler 851a309f77SMatt Spinler private: 861a309f77SMatt Spinler /** 871a309f77SMatt Spinler * @brief Determines if the BMC is in the ready state. 881a309f77SMatt Spinler * @return bool If the BMC is in the ready state 891a309f77SMatt Spinler */ 901a309f77SMatt Spinler bool isBmcReady() const; 911a309f77SMatt Spinler 921a309f77SMatt Spinler /** 931a309f77SMatt Spinler * @brief Determines if system (chassis) is powered on. 941a309f77SMatt Spinler * 951a309f77SMatt Spinler * @return bool - If power is on 961a309f77SMatt Spinler */ 971a309f77SMatt Spinler bool isPoweredOn() const; 981a309f77SMatt Spinler 991a309f77SMatt Spinler /** 1001a309f77SMatt Spinler * @brief Requests a host state transition 1011a309f77SMatt Spinler * @param[in] transition - The transition (like On or Off) 1021a309f77SMatt Spinler */ 1031a309f77SMatt Spinler void hostTransition( 1041a309f77SMatt Spinler sdbusplus::xyz::openbmc_project::State::server::Host::Transition 1051a309f77SMatt Spinler transition); 1061a309f77SMatt Spinler 1071a309f77SMatt Spinler /** 1081a309f77SMatt Spinler * @brief Powers on the system 1091a309f77SMatt Spinler */ 1101a309f77SMatt Spinler void powerOn(); 1111a309f77SMatt Spinler 1121a309f77SMatt Spinler /** 1131a309f77SMatt Spinler * @brief Requests a host power off 1141a309f77SMatt Spinler */ 1151a309f77SMatt Spinler void hostPowerOff(); 1161a309f77SMatt Spinler 1171a309f77SMatt Spinler /** 1181a309f77SMatt Spinler * @brief Requests a chassis power off 1191a309f77SMatt Spinler */ 1201a309f77SMatt Spinler void chassisPowerOff(); 1211a309f77SMatt Spinler 1221a309f77SMatt Spinler /** 1231a309f77SMatt Spinler * @brief The handler for the 1s timer that runs when determining 1241a309f77SMatt Spinler * how to power off. 1251a309f77SMatt Spinler * 1261a309f77SMatt Spinler * A 1 second timer is used so that there is the ability to emit 1271a309f77SMatt Spinler * a power off countdown if necessary. 1281a309f77SMatt Spinler */ 1291a309f77SMatt Spinler void timerHandler(); 1301a309f77SMatt Spinler 1311a309f77SMatt Spinler /** 1321a309f77SMatt Spinler * @brief Sets the time the host will be powered off if the 1331a309f77SMatt Spinler * button is still pressed - 4 seconds in the future. 1341a309f77SMatt Spinler */ setHostOffTime()1351a309f77SMatt Spinler inline void setHostOffTime() 1361a309f77SMatt Spinler { 1371a309f77SMatt Spinler hostOffTime = std::chrono::steady_clock::now() + hostOffInterval; 1381a309f77SMatt Spinler } 1391a309f77SMatt Spinler 1401a309f77SMatt Spinler /** 1411a309f77SMatt Spinler * @brief Sets the time the chassis will be powered off if the 1421a309f77SMatt Spinler * button is still pressed or pressed again - 10 seconds 1431a309f77SMatt Spinler * in the future. 1441a309f77SMatt Spinler */ setChassisOffTime()1451a309f77SMatt Spinler inline void setChassisOffTime() 1461a309f77SMatt Spinler { 1471a309f77SMatt Spinler chassisOffTime = std::chrono::steady_clock::now() + chassisOffInterval; 1481a309f77SMatt Spinler } 1491a309f77SMatt Spinler 1501a309f77SMatt Spinler /** 1511a309f77SMatt Spinler * @brief The interval the timer handler is called at. 1521a309f77SMatt Spinler */ 1531a309f77SMatt Spinler static constexpr std::chrono::milliseconds pollInterval{1000}; 1541a309f77SMatt Spinler 1551a309f77SMatt Spinler /** 1561a309f77SMatt Spinler * @brief Default button hold down interval constant 1571a309f77SMatt Spinler */ 1581a309f77SMatt Spinler static constexpr std::chrono::milliseconds hostOffInterval{4000}; 1591a309f77SMatt Spinler 1601a309f77SMatt Spinler /** 1611a309f77SMatt Spinler * @brief The time between a host power off and chassis power off. 1621a309f77SMatt Spinler */ 1631a309f77SMatt Spinler static constexpr std::chrono::milliseconds chassisOffInterval{10000}; 1641a309f77SMatt Spinler 1651a309f77SMatt Spinler /** 1661a309f77SMatt Spinler * @brief The current state of the handler. 1671a309f77SMatt Spinler */ 1681a309f77SMatt Spinler PowerOpState state; 1691a309f77SMatt Spinler 1701a309f77SMatt Spinler /** 1711a309f77SMatt Spinler * @brief When the host will be powered off. 1721a309f77SMatt Spinler */ 1731a309f77SMatt Spinler std::chrono::time_point<std::chrono::steady_clock> hostOffTime; 1741a309f77SMatt Spinler 1751a309f77SMatt Spinler /** 1761a309f77SMatt Spinler * @brief When the chassis will be powered off. 1771a309f77SMatt Spinler */ 1781a309f77SMatt Spinler std::chrono::time_point<std::chrono::steady_clock> chassisOffTime; 1791a309f77SMatt Spinler 1801a309f77SMatt Spinler /** 1811a309f77SMatt Spinler * @brief The timer object. 1821a309f77SMatt Spinler */ 1831a309f77SMatt Spinler sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> timer; 1841a309f77SMatt Spinler }; 1851a309f77SMatt Spinler } // namespace phosphor::button 186