xref: /openbmc/phosphor-buttons/src/button_handler.cpp (revision 31ce375e7e71ff6b3da460dc63c1ab4f16cf4df6)
1d6a1bae7SGeorge Liu #include "button_handler.hpp"
269f93512SMatt Spinler 
315c60e2fSDelphine CC Chiu #include "config.hpp"
4*31ce375eSRush Chen #include "gpio.hpp"
51a309f77SMatt Spinler #include "power_button_profile_factory.hpp"
61a309f77SMatt Spinler 
79fb15970SGeorge Liu #include <phosphor-logging/lg2.hpp>
8*31ce375eSRush Chen #include <xyz/openbmc_project/Chassis/Buttons/Power/server.hpp>
9963c65f3SMatt Spinler #include <xyz/openbmc_project/State/Chassis/server.hpp>
10963c65f3SMatt Spinler #include <xyz/openbmc_project/State/Host/server.hpp>
11*31ce375eSRush Chen 
12*31ce375eSRush Chen #include <fstream>
13*31ce375eSRush Chen #include <iostream>
14*31ce375eSRush Chen #include <string>
15*31ce375eSRush Chen 
16fb35a325SMatt Spinler namespace phosphor
17fb35a325SMatt Spinler {
18fb35a325SMatt Spinler namespace button
19fb35a325SMatt Spinler {
20963c65f3SMatt Spinler 
21963c65f3SMatt Spinler namespace sdbusRule = sdbusplus::bus::match::rules;
22963c65f3SMatt Spinler using namespace sdbusplus::xyz::openbmc_project::State::server;
23*31ce375eSRush Chen using namespace sdbusplus::xyz::openbmc_project::Chassis::Buttons::server;
24*31ce375eSRush Chen 
25*31ce375eSRush Chen const std::map<std::string, Chassis::Transition> chassisPwrCtls = {
26*31ce375eSRush Chen     {"chassis-on", Chassis::Transition::On},
27*31ce375eSRush Chen     {"chassis-off", Chassis::Transition::Off},
28*31ce375eSRush Chen     {"chassis-cycle", Chassis::Transition::PowerCycle}};
29963c65f3SMatt Spinler 
30963c65f3SMatt Spinler constexpr auto chassisIface = "xyz.openbmc_project.State.Chassis";
31963c65f3SMatt Spinler constexpr auto hostIface = "xyz.openbmc_project.State.Host";
32963c65f3SMatt Spinler constexpr auto powerButtonIface = "xyz.openbmc_project.Chassis.Buttons.Power";
3369f93512SMatt Spinler constexpr auto idButtonIface = "xyz.openbmc_project.Chassis.Buttons.ID";
3406a5bddfSMatt Spinler constexpr auto resetButtonIface = "xyz.openbmc_project.Chassis.Buttons.Reset";
3569f93512SMatt Spinler constexpr auto ledGroupIface = "xyz.openbmc_project.Led.Group";
363bd1cfcbSNaveen Moses constexpr auto ledGroupBasePath = "/xyz/openbmc_project/led/groups/";
373bd1cfcbSNaveen Moses constexpr auto hostSelectorIface =
383bd1cfcbSNaveen Moses     "xyz.openbmc_project.Chassis.Buttons.HostSelector";
393bd1cfcbSNaveen Moses constexpr auto debugHostSelectorIface =
40a6d4e65dSNaveen Moses     "xyz.openbmc_project.Chassis.Buttons.Button";
413bd1cfcbSNaveen Moses 
423bd1cfcbSNaveen Moses constexpr auto propertyIface = "org.freedesktop.DBus.Properties";
433bd1cfcbSNaveen Moses constexpr auto mapperIface = "xyz.openbmc_project.ObjectMapper";
44963c65f3SMatt Spinler 
45963c65f3SMatt Spinler constexpr auto mapperObjPath = "/xyz/openbmc_project/object_mapper";
46963c65f3SMatt Spinler constexpr auto mapperService = "xyz.openbmc_project.ObjectMapper";
473bd1cfcbSNaveen Moses constexpr auto BMC_POSITION = 0;
48963c65f3SMatt Spinler 
49*31ce375eSRush Chen std::vector<std::map<uint16_t, Chassis::Transition>> multiPwrBtnActConf;
50*31ce375eSRush Chen 
Handler(sdbusplus::bus_t & bus)519a529a69SPatrick Williams Handler::Handler(sdbusplus::bus_t& bus) : bus(bus)
52fb35a325SMatt Spinler {
53*31ce375eSRush Chen     /* So far, there are two modes for multi-host power control
54*31ce375eSRush Chen     - host select button mode, e.g.: Yosemite V2
55*31ce375eSRush Chen     only one power button with host select switch,
56*31ce375eSRush Chen     which's interface for handling target host,
57*31ce375eSRush Chen     in the case, hostSelectButtonMode = true
58*31ce375eSRush Chen     - multi power button mode, e.g.: Greatlakes
59*31ce375eSRush Chen     each slot/sled has its own power button,
60*31ce375eSRush Chen     in the case, hostSelectButtonMode = false */
61*31ce375eSRush Chen     hostSelectButtonMode =
62*31ce375eSRush Chen         !getService(HS_DBUS_OBJECT_NAME, hostSelectorIface).empty();
63*31ce375eSRush Chen     size_t powerButtonCount = 1;
64*31ce375eSRush Chen     if (!hostSelectButtonMode)
65*31ce375eSRush Chen     {
66*31ce375eSRush Chen         powerButtonCount = phosphor::button::numberOfChassis();
67*31ce375eSRush Chen     }
68*31ce375eSRush Chen 
69*31ce375eSRush Chen     std::ifstream gpios{gpioDefFile};
70*31ce375eSRush Chen     auto configDefJson = nlohmann::json::parse(gpios, nullptr, true);
71*31ce375eSRush Chen     nlohmann::json gpioDefs = configDefJson["gpio_definitions"];
72*31ce375eSRush Chen 
73*31ce375eSRush Chen     for (const auto& gpioConfig : gpioDefs)
74*31ce375eSRush Chen     {
75*31ce375eSRush Chen         if (gpioConfig.contains("multi-action"))
76*31ce375eSRush Chen         {
77*31ce375eSRush Chen             std::map<uint16_t, Chassis::Transition> mapEntry;
78*31ce375eSRush Chen             const auto& multiActCfg = gpioConfig["multi-action"];
79*31ce375eSRush Chen             for (const auto& ActCfg : multiActCfg)
80*31ce375eSRush Chen             {
81*31ce375eSRush Chen                 auto chassisPwrCtl = chassisPwrCtls.find(ActCfg["action"]);
82*31ce375eSRush Chen                 if (chassisPwrCtl != chassisPwrCtls.end())
83*31ce375eSRush Chen                 {
84*31ce375eSRush Chen                     auto duration = ActCfg["duration"].get<uint16_t>();
85*31ce375eSRush Chen                     mapEntry[duration] = chassisPwrCtl->second;
86*31ce375eSRush Chen                 }
87*31ce375eSRush Chen                 else
88*31ce375eSRush Chen                 {
89*31ce375eSRush Chen                     lg2::error("unknown power button action");
90*31ce375eSRush Chen                 }
91*31ce375eSRush Chen             }
92*31ce375eSRush Chen             multiPwrBtnActConf.emplace_back(mapEntry);
93*31ce375eSRush Chen         }
94*31ce375eSRush Chen         else
95*31ce375eSRush Chen         {
96*31ce375eSRush Chen             isButtonMultiActionSupport = false;
97*31ce375eSRush Chen             break;
98*31ce375eSRush Chen         }
99*31ce375eSRush Chen     }
100*31ce375eSRush Chen 
101963c65f3SMatt Spinler     try
102963c65f3SMatt Spinler     {
103963c65f3SMatt Spinler         if (!getService(POWER_DBUS_OBJECT_NAME, powerButtonIface).empty())
104963c65f3SMatt Spinler         {
1059fb15970SGeorge Liu             lg2::info("Starting power button handler");
1061a309f77SMatt Spinler 
1071a309f77SMatt Spinler             // Check for a custom handler
1081a309f77SMatt Spinler             powerButtonProfile =
1091a309f77SMatt Spinler                 PowerButtonProfileFactory::instance().createProfile(bus);
1101a309f77SMatt Spinler 
1111a309f77SMatt Spinler             if (!powerButtonProfile)
1121a309f77SMatt Spinler             {
113963c65f3SMatt Spinler                 powerButtonReleased = std::make_unique<sdbusplus::bus::match_t>(
114963c65f3SMatt Spinler                     bus,
115963c65f3SMatt Spinler                     sdbusRule::type::signal() + sdbusRule::member("Released") +
116963c65f3SMatt Spinler                         sdbusRule::path(POWER_DBUS_OBJECT_NAME) +
117963c65f3SMatt Spinler                         sdbusRule::interface(powerButtonIface),
118ab8dac51SNaveen Moses                     std::bind(std::mem_fn(&Handler::powerReleased), this,
119963c65f3SMatt Spinler                               std::placeholders::_1));
120963c65f3SMatt Spinler             }
121963c65f3SMatt Spinler         }
122*31ce375eSRush Chen 
123*31ce375eSRush Chen         if (!hostSelectButtonMode && isButtonMultiActionSupport)
124*31ce375eSRush Chen         {
125*31ce375eSRush Chen             lg2::info("Starting multi power button handler");
126*31ce375eSRush Chen             // The index, 'countIter', starts at 1 and increments,
127*31ce375eSRush Chen             // representing slot_1 through slot_N.
128*31ce375eSRush Chen             for (size_t countIter = 1; countIter <= powerButtonCount;
129*31ce375eSRush Chen                  countIter++)
130*31ce375eSRush Chen             {
131*31ce375eSRush Chen                 std::unique_ptr<sdbusplus::bus::match_t>
132*31ce375eSRush Chen                     multiPowerReleaseMatch =
133*31ce375eSRush Chen                         std::make_unique<sdbusplus::bus::match_t>(
134*31ce375eSRush Chen                             bus,
135*31ce375eSRush Chen                             sdbusRule::type::signal() +
136*31ce375eSRush Chen                                 sdbusRule::member("Released") +
137*31ce375eSRush Chen                                 sdbusRule::path(POWER_DBUS_OBJECT_NAME +
138*31ce375eSRush Chen                                                 std::to_string(countIter)) +
139*31ce375eSRush Chen                                 sdbusRule::interface(powerButtonIface),
140*31ce375eSRush Chen                             std::bind(std::mem_fn(&Handler::powerReleased),
141*31ce375eSRush Chen                                       this, std::placeholders::_1));
142*31ce375eSRush Chen                 multiPowerButtonReleased.emplace_back(
143*31ce375eSRush Chen                     std::move(multiPowerReleaseMatch));
144*31ce375eSRush Chen             }
145*31ce375eSRush Chen         }
1461a309f77SMatt Spinler     }
1479a529a69SPatrick Williams     catch (const sdbusplus::exception_t& e)
148963c65f3SMatt Spinler     {
149*31ce375eSRush Chen         lg2::error("Error creating power button handler: {ERROR}", "ERROR", e);
150963c65f3SMatt Spinler     }
15106a5bddfSMatt Spinler 
15206a5bddfSMatt Spinler     try
15306a5bddfSMatt Spinler     {
15469f93512SMatt Spinler         if (!getService(ID_DBUS_OBJECT_NAME, idButtonIface).empty())
15569f93512SMatt Spinler         {
1569fb15970SGeorge Liu             lg2::info("Registering ID button handler");
15769f93512SMatt Spinler             idButtonReleased = std::make_unique<sdbusplus::bus::match_t>(
15869f93512SMatt Spinler                 bus,
15969f93512SMatt Spinler                 sdbusRule::type::signal() + sdbusRule::member("Released") +
16069f93512SMatt Spinler                     sdbusRule::path(ID_DBUS_OBJECT_NAME) +
16169f93512SMatt Spinler                     sdbusRule::interface(idButtonIface),
162ab8dac51SNaveen Moses                 std::bind(std::mem_fn(&Handler::idReleased), this,
16369f93512SMatt Spinler                           std::placeholders::_1));
16469f93512SMatt Spinler         }
16569f93512SMatt Spinler     }
1669a529a69SPatrick Williams     catch (const sdbusplus::exception_t& e)
16769f93512SMatt Spinler     {
16869f93512SMatt Spinler         // The button wasn't implemented
16969f93512SMatt Spinler     }
17069f93512SMatt Spinler 
17169f93512SMatt Spinler     try
17269f93512SMatt Spinler     {
17306a5bddfSMatt Spinler         if (!getService(RESET_DBUS_OBJECT_NAME, resetButtonIface).empty())
17406a5bddfSMatt Spinler         {
1759fb15970SGeorge Liu             lg2::info("Registering reset button handler");
17606a5bddfSMatt Spinler             resetButtonReleased = std::make_unique<sdbusplus::bus::match_t>(
17706a5bddfSMatt Spinler                 bus,
17806a5bddfSMatt Spinler                 sdbusRule::type::signal() + sdbusRule::member("Released") +
17906a5bddfSMatt Spinler                     sdbusRule::path(RESET_DBUS_OBJECT_NAME) +
18006a5bddfSMatt Spinler                     sdbusRule::interface(resetButtonIface),
181ab8dac51SNaveen Moses                 std::bind(std::mem_fn(&Handler::resetReleased), this,
18206a5bddfSMatt Spinler                           std::placeholders::_1));
18306a5bddfSMatt Spinler         }
18406a5bddfSMatt Spinler     }
1859a529a69SPatrick Williams     catch (const sdbusplus::exception_t& e)
18606a5bddfSMatt Spinler     {
18706a5bddfSMatt Spinler         // The button wasn't implemented
18806a5bddfSMatt Spinler     }
189a6d4e65dSNaveen Moses     try
190a6d4e65dSNaveen Moses     {
191a6d4e65dSNaveen Moses         if (!getService(DBG_HS_DBUS_OBJECT_NAME, debugHostSelectorIface)
192a6d4e65dSNaveen Moses                  .empty())
193a6d4e65dSNaveen Moses         {
194a6d4e65dSNaveen Moses             lg2::info("Registering debug host selector button handler");
195a6d4e65dSNaveen Moses             debugHSButtonReleased = std::make_unique<sdbusplus::bus::match_t>(
196a6d4e65dSNaveen Moses                 bus,
197a6d4e65dSNaveen Moses                 sdbusRule::type::signal() + sdbusRule::member("Released") +
198a6d4e65dSNaveen Moses                     sdbusRule::path(DBG_HS_DBUS_OBJECT_NAME) +
199a6d4e65dSNaveen Moses                     sdbusRule::interface(debugHostSelectorIface),
200a6d4e65dSNaveen Moses                 std::bind(std::mem_fn(&Handler::debugHostSelectorReleased),
201a6d4e65dSNaveen Moses                           this, std::placeholders::_1));
202a6d4e65dSNaveen Moses         }
203a6d4e65dSNaveen Moses     }
204e3b4e11fSPatrick Williams     catch (const sdbusplus::exception_t& e)
205a6d4e65dSNaveen Moses     {
206a6d4e65dSNaveen Moses         // The button wasn't implemented
207a6d4e65dSNaveen Moses     }
208963c65f3SMatt Spinler }
isMultiHost()2093bd1cfcbSNaveen Moses bool Handler::isMultiHost()
2103bd1cfcbSNaveen Moses {
211*31ce375eSRush Chen     if (numberOfChassis() != 1)
212*31ce375eSRush Chen     {
213*31ce375eSRush Chen         return true;
214*31ce375eSRush Chen     }
215*31ce375eSRush Chen     else
216*31ce375eSRush Chen     {
217*31ce375eSRush Chen         return (hostSelectButtonMode);
218*31ce375eSRush Chen     }
2193bd1cfcbSNaveen Moses }
getService(const std::string & path,const std::string & interface) const220963c65f3SMatt Spinler std::string Handler::getService(const std::string& path,
221963c65f3SMatt Spinler                                 const std::string& interface) const
222963c65f3SMatt Spinler {
223963c65f3SMatt Spinler     auto method = bus.new_method_call(mapperService, mapperObjPath, mapperIface,
224963c65f3SMatt Spinler                                       "GetObject");
225963c65f3SMatt Spinler     method.append(path, std::vector{interface});
22642507857SThang Q. Nguyen     try
22742507857SThang Q. Nguyen     {
228963c65f3SMatt Spinler         auto result = bus.call(method);
229963c65f3SMatt Spinler         std::map<std::string, std::vector<std::string>> objectData;
230963c65f3SMatt Spinler         result.read(objectData);
231963c65f3SMatt Spinler         return objectData.begin()->first;
232963c65f3SMatt Spinler     }
233e3b4e11fSPatrick Williams     catch (const sdbusplus::exception_t& e)
23442507857SThang Q. Nguyen     {
23542507857SThang Q. Nguyen         return std::string();
23642507857SThang Q. Nguyen     }
23742507857SThang Q. Nguyen }
getHostSelectorValue()2383bd1cfcbSNaveen Moses size_t Handler::getHostSelectorValue()
239963c65f3SMatt Spinler {
2403bd1cfcbSNaveen Moses     auto HSService = getService(HS_DBUS_OBJECT_NAME, hostSelectorIface);
2413bd1cfcbSNaveen Moses 
2423bd1cfcbSNaveen Moses     if (HSService.empty())
2433bd1cfcbSNaveen Moses     {
244a6d4e65dSNaveen Moses         lg2::info("Host selector dbus object not available");
2453bd1cfcbSNaveen Moses         throw std::invalid_argument("Host selector dbus object not available");
2463bd1cfcbSNaveen Moses     }
2473bd1cfcbSNaveen Moses 
2483bd1cfcbSNaveen Moses     try
2493bd1cfcbSNaveen Moses     {
250963c65f3SMatt Spinler         auto method = bus.new_method_call(
2513bd1cfcbSNaveen Moses             HSService.c_str(), HS_DBUS_OBJECT_NAME, propertyIface, "Get");
2523bd1cfcbSNaveen Moses         method.append(hostSelectorIface, "Position");
2533bd1cfcbSNaveen Moses         auto result = bus.call(method);
2543bd1cfcbSNaveen Moses 
2553bd1cfcbSNaveen Moses         std::variant<size_t> HSPositionVariant;
2563bd1cfcbSNaveen Moses         result.read(HSPositionVariant);
2573bd1cfcbSNaveen Moses 
2583bd1cfcbSNaveen Moses         auto position = std::get<size_t>(HSPositionVariant);
2593bd1cfcbSNaveen Moses         return position;
2603bd1cfcbSNaveen Moses     }
2619a529a69SPatrick Williams     catch (const sdbusplus::exception_t& e)
2623bd1cfcbSNaveen Moses     {
263a6d4e65dSNaveen Moses         lg2::error("Error reading host selector position: {ERROR}", "ERROR", e);
2643bd1cfcbSNaveen Moses         throw;
2653bd1cfcbSNaveen Moses     }
2663bd1cfcbSNaveen Moses }
poweredOn(size_t hostNumber) const2673bd1cfcbSNaveen Moses bool Handler::poweredOn(size_t hostNumber) const
2683bd1cfcbSNaveen Moses {
269c0fee46eSPotin Lai     auto hostObjectName = HOST_STATE_OBJECT_NAME + std::to_string(hostNumber);
270c0fee46eSPotin Lai     auto service = getService(hostObjectName.c_str(), hostIface);
271c0fee46eSPotin Lai     auto method = bus.new_method_call(service.c_str(), hostObjectName.c_str(),
272c0fee46eSPotin Lai                                       propertyIface, "Get");
273c0fee46eSPotin Lai     method.append(hostIface, "CurrentHostState");
274963c65f3SMatt Spinler     auto result = bus.call(method);
275963c65f3SMatt Spinler 
2765ed4cc0fSPatrick Williams     std::variant<std::string> state;
277963c65f3SMatt Spinler     result.read(state);
278963c65f3SMatt Spinler 
279c0fee46eSPotin Lai     return Host::HostState::Off !=
280c0fee46eSPotin Lai            Host::convertHostStateFromString(std::get<std::string>(state));
281963c65f3SMatt Spinler }
282963c65f3SMatt Spinler 
handlePowerEvent(PowerEvent powerEventType,const std::string & objectPath,std::chrono::microseconds duration)283395c764cSDelphineCCChiu void Handler::handlePowerEvent(PowerEvent powerEventType,
284*31ce375eSRush Chen                                const std::string& objectPath,
285395c764cSDelphineCCChiu                                std::chrono::microseconds duration)
286963c65f3SMatt Spinler {
2873bd1cfcbSNaveen Moses     std::string objPathName;
2883bd1cfcbSNaveen Moses     std::string dbusIfaceName;
2893bd1cfcbSNaveen Moses     std::string transitionName;
2903bd1cfcbSNaveen Moses     std::variant<Host::Transition, Chassis::Transition> transition;
291963c65f3SMatt Spinler 
2923bd1cfcbSNaveen Moses     size_t hostNumber = 0;
293*31ce375eSRush Chen     std::string hostNumStr =
294*31ce375eSRush Chen         objectPath.substr(std::string(POWER_DBUS_OBJECT_NAME).length());
2953bd1cfcbSNaveen Moses     auto isMultiHostSystem = isMultiHost();
296*31ce375eSRush Chen 
297*31ce375eSRush Chen     if (hostSelectButtonMode)
298963c65f3SMatt Spinler     {
2993bd1cfcbSNaveen Moses         hostNumber = getHostSelectorValue();
300a6d4e65dSNaveen Moses         lg2::info("Multi-host system detected : {POSITION}", "POSITION",
3019fb15970SGeorge Liu                   hostNumber);
3023bd1cfcbSNaveen Moses 
303*31ce375eSRush Chen         hostNumStr = std::to_string(hostNumber);
3043bd1cfcbSNaveen Moses 
3053bd1cfcbSNaveen Moses         // ignore  power and reset button events if BMC is selected.
3063bd1cfcbSNaveen Moses         if (isMultiHostSystem && (hostNumber == BMC_POSITION) &&
307395c764cSDelphineCCChiu             (powerEventType != PowerEvent::powerReleased) &&
308971312abSPatrick Williams             (duration <= LONG_PRESS_TIME_MS))
3093bd1cfcbSNaveen Moses         {
3109fb15970SGeorge Liu             lg2::info(
311a6d4e65dSNaveen Moses                 "handlePowerEvent : BMC selected on multi-host system. ignoring power and reset button events...");
3123bd1cfcbSNaveen Moses             return;
3133bd1cfcbSNaveen Moses         }
314*31ce375eSRush Chen     }
3153bd1cfcbSNaveen Moses 
3163bd1cfcbSNaveen Moses     switch (powerEventType)
3173bd1cfcbSNaveen Moses     {
318ab8dac51SNaveen Moses         case PowerEvent::powerReleased:
3195b98f4dbSGeorge Liu         {
320*31ce375eSRush Chen             for (const auto& iter : multiPwrBtnActConf[stoi(hostNumStr) - 1])
321*31ce375eSRush Chen             {
322*31ce375eSRush Chen                 if (duration > std::chrono::milliseconds(iter.first))
323*31ce375eSRush Chen                 {
324*31ce375eSRush Chen                     dbusIfaceName = chassisIface;
325*31ce375eSRush Chen                     transitionName = "RequestedPowerTransition";
326*31ce375eSRush Chen                     objPathName = CHASSIS_STATE_OBJECT_NAME + hostNumStr;
327*31ce375eSRush Chen                     transition = iter.second;
328*31ce375eSRush Chen                 }
329*31ce375eSRush Chen             }
330*31ce375eSRush Chen             break;
331*31ce375eSRush Chen 
332971312abSPatrick Williams             if (duration <= LONG_PRESS_TIME_MS)
333395c764cSDelphineCCChiu             {
3343bd1cfcbSNaveen Moses                 objPathName = HOST_STATE_OBJECT_NAME + hostNumStr;
3353bd1cfcbSNaveen Moses                 dbusIfaceName = hostIface;
3363bd1cfcbSNaveen Moses                 transitionName = "RequestedHostTransition";
3373bd1cfcbSNaveen Moses 
3383bd1cfcbSNaveen Moses                 transition = Host::Transition::On;
3393bd1cfcbSNaveen Moses 
3403bd1cfcbSNaveen Moses                 if (poweredOn(hostNumber))
341963c65f3SMatt Spinler                 {
342963c65f3SMatt Spinler                     transition = Host::Transition::Off;
343963c65f3SMatt Spinler                 }
344a6d4e65dSNaveen Moses                 lg2::info("handlePowerEvent : Handle power button press ");
3453bd1cfcbSNaveen Moses                 break;
3463bd1cfcbSNaveen Moses             }
347395c764cSDelphineCCChiu             else
3485b98f4dbSGeorge Liu             {
3493bd1cfcbSNaveen Moses                 dbusIfaceName = chassisIface;
3503bd1cfcbSNaveen Moses                 transitionName = "RequestedPowerTransition";
3513bd1cfcbSNaveen Moses                 objPathName = CHASSIS_STATE_OBJECT_NAME + hostNumStr;
3523bd1cfcbSNaveen Moses                 transition = Chassis::Transition::Off;
353963c65f3SMatt Spinler 
3543bd1cfcbSNaveen Moses                 /*  multi host system :
3553bd1cfcbSNaveen Moses                         hosts (1 to N) - host shutdown
3563bd1cfcbSNaveen Moses                         bmc (0) - sled cycle
3573bd1cfcbSNaveen Moses                     single host system :
3583bd1cfcbSNaveen Moses                         host(0) - host shutdown
3593bd1cfcbSNaveen Moses                 */
3603bd1cfcbSNaveen Moses                 if (isMultiHostSystem && (hostNumber == BMC_POSITION))
3613bd1cfcbSNaveen Moses                 {
3623bd1cfcbSNaveen Moses #if CHASSIS_SYSTEM_RESET_ENABLED
3633bd1cfcbSNaveen Moses                     objPathName = CHASSISSYSTEM_STATE_OBJECT_NAME + hostNumStr;
3643bd1cfcbSNaveen Moses                     transition = Chassis::Transition::PowerCycle;
3653bd1cfcbSNaveen Moses #else
3663bd1cfcbSNaveen Moses                     return;
3673bd1cfcbSNaveen Moses #endif
3683bd1cfcbSNaveen Moses                 }
3693bd1cfcbSNaveen Moses                 else if (!poweredOn(hostNumber))
3703bd1cfcbSNaveen Moses                 {
371395c764cSDelphineCCChiu                     lg2::info(
372395c764cSDelphineCCChiu                         "Power is off so ignoring long power button press");
3733bd1cfcbSNaveen Moses                     return;
3743bd1cfcbSNaveen Moses                 }
3759fb15970SGeorge Liu                 lg2::info("handlePowerEvent : handle long power button press");
3763bd1cfcbSNaveen Moses                 break;
3773bd1cfcbSNaveen Moses             }
378395c764cSDelphineCCChiu         }
379ab8dac51SNaveen Moses         case PowerEvent::resetReleased:
3805b98f4dbSGeorge Liu         {
3813bd1cfcbSNaveen Moses             objPathName = HOST_STATE_OBJECT_NAME + hostNumStr;
3823bd1cfcbSNaveen Moses             dbusIfaceName = hostIface;
3833bd1cfcbSNaveen Moses             transitionName = "RequestedHostTransition";
3843bd1cfcbSNaveen Moses 
3853bd1cfcbSNaveen Moses             if (!poweredOn(hostNumber))
3863bd1cfcbSNaveen Moses             {
3879fb15970SGeorge Liu                 lg2::info("Power is off so ignoring reset button press");
3883bd1cfcbSNaveen Moses                 return;
3893bd1cfcbSNaveen Moses             }
3903bd1cfcbSNaveen Moses 
3919fb15970SGeorge Liu             lg2::info("Handling reset button press");
3929456ffc9SHuyLe #ifdef ENABLE_RESET_BUTTON_DO_WARM_REBOOT
3939456ffc9SHuyLe             transition = Host::Transition::ForceWarmReboot;
3949456ffc9SHuyLe #else
3953bd1cfcbSNaveen Moses             transition = Host::Transition::Reboot;
3969456ffc9SHuyLe #endif
3973bd1cfcbSNaveen Moses             break;
3983bd1cfcbSNaveen Moses         }
3995b98f4dbSGeorge Liu         default:
4005b98f4dbSGeorge Liu         {
4019fb15970SGeorge Liu             lg2::error("{EVENT} is invalid power event. skipping...", "EVENT",
4023610608cSPatrick Williams                        powerEventType);
4033bd1cfcbSNaveen Moses 
4043bd1cfcbSNaveen Moses             return;
4053bd1cfcbSNaveen Moses         }
4063bd1cfcbSNaveen Moses     }
4073bd1cfcbSNaveen Moses     auto service = getService(objPathName.c_str(), dbusIfaceName);
4083bd1cfcbSNaveen Moses     auto method = bus.new_method_call(service.c_str(), objPathName.c_str(),
4093bd1cfcbSNaveen Moses                                       propertyIface, "Set");
4103bd1cfcbSNaveen Moses     method.append(dbusIfaceName, transitionName, transition);
411963c65f3SMatt Spinler     bus.call(method);
412963c65f3SMatt Spinler }
413*31ce375eSRush Chen 
powerReleased(sdbusplus::message_t & msg)414395c764cSDelphineCCChiu void Handler::powerReleased(sdbusplus::message_t& msg)
4153bd1cfcbSNaveen Moses {
4163bd1cfcbSNaveen Moses     try
4173bd1cfcbSNaveen Moses     {
418395c764cSDelphineCCChiu         uint64_t time;
419395c764cSDelphineCCChiu         msg.read(time);
420395c764cSDelphineCCChiu 
421*31ce375eSRush Chen         handlePowerEvent(PowerEvent::powerReleased, msg.get_path(),
422395c764cSDelphineCCChiu                          std::chrono::microseconds(time));
4233bd1cfcbSNaveen Moses     }
4249a529a69SPatrick Williams     catch (const sdbusplus::exception_t& e)
425963c65f3SMatt Spinler     {
4269fb15970SGeorge Liu         lg2::error("Failed power state change on a power button press: {ERROR}",
4279fb15970SGeorge Liu                    "ERROR", e);
428963c65f3SMatt Spinler     }
429963c65f3SMatt Spinler }
43006a5bddfSMatt Spinler 
resetReleased(sdbusplus::message_t & msg)431*31ce375eSRush Chen void Handler::resetReleased(sdbusplus::message_t& msg)
43206a5bddfSMatt Spinler {
43306a5bddfSMatt Spinler     try
43406a5bddfSMatt Spinler     {
435395c764cSDelphineCCChiu         // No need to calculate duration, set to 0.
436*31ce375eSRush Chen         handlePowerEvent(PowerEvent::resetReleased, msg.get_path(),
437395c764cSDelphineCCChiu                          std::chrono::microseconds(0));
43806a5bddfSMatt Spinler     }
4399a529a69SPatrick Williams     catch (const sdbusplus::exception_t& e)
44006a5bddfSMatt Spinler     {
4419fb15970SGeorge Liu         lg2::error("Failed power state change on a reset button press: {ERROR}",
4429fb15970SGeorge Liu                    "ERROR", e);
44306a5bddfSMatt Spinler     }
44406a5bddfSMatt Spinler }
44569f93512SMatt Spinler 
idReleased(sdbusplus::message_t &)4469a529a69SPatrick Williams void Handler::idReleased(sdbusplus::message_t& /* msg */)
44769f93512SMatt Spinler {
44869f93512SMatt Spinler     std::string groupPath{ledGroupBasePath};
44969f93512SMatt Spinler     groupPath += ID_LED_GROUP;
45069f93512SMatt Spinler 
45169f93512SMatt Spinler     auto service = getService(groupPath, ledGroupIface);
45269f93512SMatt Spinler 
45369f93512SMatt Spinler     if (service.empty())
45469f93512SMatt Spinler     {
4559fb15970SGeorge Liu         lg2::info("No found {GROUP} during ID button press:", "GROUP",
4569fb15970SGeorge Liu                   groupPath);
45769f93512SMatt Spinler         return;
45869f93512SMatt Spinler     }
45969f93512SMatt Spinler 
46069f93512SMatt Spinler     try
46169f93512SMatt Spinler     {
46269f93512SMatt Spinler         auto method = bus.new_method_call(service.c_str(), groupPath.c_str(),
46369f93512SMatt Spinler                                           propertyIface, "Get");
46469f93512SMatt Spinler         method.append(ledGroupIface, "Asserted");
46569f93512SMatt Spinler         auto result = bus.call(method);
46669f93512SMatt Spinler 
4675ed4cc0fSPatrick Williams         std::variant<bool> state;
46869f93512SMatt Spinler         result.read(state);
46969f93512SMatt Spinler 
47051f5e8bdSPatrick Williams         state = !std::get<bool>(state);
47169f93512SMatt Spinler 
4729fb15970SGeorge Liu         lg2::info(
4739fb15970SGeorge Liu             "Changing ID LED group state on ID LED press, GROUP = {GROUP}, STATE = {STATE}",
4749fb15970SGeorge Liu             "GROUP", groupPath, "STATE", std::get<bool>(state));
47569f93512SMatt Spinler 
47669f93512SMatt Spinler         method = bus.new_method_call(service.c_str(), groupPath.c_str(),
47769f93512SMatt Spinler                                      propertyIface, "Set");
47869f93512SMatt Spinler 
47969f93512SMatt Spinler         method.append(ledGroupIface, "Asserted", state);
48069f93512SMatt Spinler         result = bus.call(method);
48169f93512SMatt Spinler     }
4829a529a69SPatrick Williams     catch (const sdbusplus::exception_t& e)
48369f93512SMatt Spinler     {
4849fb15970SGeorge Liu         lg2::error("Error toggling ID LED group on ID button press: {ERROR}",
4859fb15970SGeorge Liu                    "ERROR", e);
48669f93512SMatt Spinler     }
48769f93512SMatt Spinler }
488a6d4e65dSNaveen Moses 
increaseHostSelectorPosition()489a6d4e65dSNaveen Moses void Handler::increaseHostSelectorPosition()
490a6d4e65dSNaveen Moses {
491a6d4e65dSNaveen Moses     try
492a6d4e65dSNaveen Moses     {
493a6d4e65dSNaveen Moses         auto HSService = getService(HS_DBUS_OBJECT_NAME, hostSelectorIface);
494a6d4e65dSNaveen Moses 
495a6d4e65dSNaveen Moses         if (HSService.empty())
496a6d4e65dSNaveen Moses         {
497a6d4e65dSNaveen Moses             lg2::error("Host selector service not available");
498a6d4e65dSNaveen Moses             return;
499a6d4e65dSNaveen Moses         }
500a6d4e65dSNaveen Moses 
501a6d4e65dSNaveen Moses         auto method =
502a6d4e65dSNaveen Moses             bus.new_method_call(HSService.c_str(), HS_DBUS_OBJECT_NAME,
503a6d4e65dSNaveen Moses                                 phosphor::button::propertyIface, "GetAll");
504a6d4e65dSNaveen Moses         method.append(phosphor::button::hostSelectorIface);
505a6d4e65dSNaveen Moses         auto result = bus.call(method);
506a6d4e65dSNaveen Moses         std::unordered_map<std::string, std::variant<size_t>> properties;
507a6d4e65dSNaveen Moses         result.read(properties);
508a6d4e65dSNaveen Moses 
509a6d4e65dSNaveen Moses         auto maxPosition = std::get<size_t>(properties.at("MaxPosition"));
510a6d4e65dSNaveen Moses         auto position = std::get<size_t>(properties.at("Position"));
511a6d4e65dSNaveen Moses 
512a6d4e65dSNaveen Moses         std::variant<size_t> HSPositionVariant =
513a6d4e65dSNaveen Moses             (position < maxPosition) ? (position + 1) : 0;
514a6d4e65dSNaveen Moses 
515a6d4e65dSNaveen Moses         method = bus.new_method_call(HSService.c_str(), HS_DBUS_OBJECT_NAME,
516a6d4e65dSNaveen Moses                                      phosphor::button::propertyIface, "Set");
517a6d4e65dSNaveen Moses         method.append(phosphor::button::hostSelectorIface, "Position");
518a6d4e65dSNaveen Moses 
519a6d4e65dSNaveen Moses         method.append(HSPositionVariant);
520a6d4e65dSNaveen Moses         result = bus.call(method);
521a6d4e65dSNaveen Moses     }
522e3b4e11fSPatrick Williams     catch (const sdbusplus::exception_t& e)
523a6d4e65dSNaveen Moses     {
524a6d4e65dSNaveen Moses         lg2::error("Error modifying host selector position : {ERROR}", "ERROR",
525a6d4e65dSNaveen Moses                    e);
526a6d4e65dSNaveen Moses     }
527a6d4e65dSNaveen Moses }
528a6d4e65dSNaveen Moses 
debugHostSelectorReleased(sdbusplus::message_t &)529e3b4e11fSPatrick Williams void Handler::debugHostSelectorReleased(sdbusplus::message_t& /* msg */)
530a6d4e65dSNaveen Moses {
531a6d4e65dSNaveen Moses     try
532a6d4e65dSNaveen Moses     {
533a6d4e65dSNaveen Moses         increaseHostSelectorPosition();
534a6d4e65dSNaveen Moses     }
535e3b4e11fSPatrick Williams     catch (const sdbusplus::exception_t& e)
536a6d4e65dSNaveen Moses     {
537a6d4e65dSNaveen Moses         lg2::error(
538a6d4e65dSNaveen Moses             "Failed power process debug host selector button press : {ERROR}",
539a6d4e65dSNaveen Moses             "ERROR", e);
540a6d4e65dSNaveen Moses     }
541a6d4e65dSNaveen Moses }
542a6d4e65dSNaveen Moses 
543fb35a325SMatt Spinler } // namespace button
544fb35a325SMatt Spinler } // namespace phosphor
545