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