blob: f18f1b5ced8cb9998b8b0ce00d1638aa751b27aa [file] [log] [blame]
George Liud6a1bae2022-06-20 13:47:31 +08001#include "button_handler.hpp"
Matt Spinler69f93512018-11-26 14:55:58 -06002
Delphine CC Chiu15c60e22024-04-12 13:01:32 -05003#include "config.hpp"
Rush Chen31ce3752024-11-08 14:57:27 +08004#include "gpio.hpp"
Matt Spinler1a309f72023-04-04 13:12:19 -05005#include "power_button_profile_factory.hpp"
6
George Liu9fb15972022-06-20 14:54:38 +08007#include <phosphor-logging/lg2.hpp>
Rush Chen31ce3752024-11-08 14:57:27 +08008#include <xyz/openbmc_project/Chassis/Buttons/Power/server.hpp>
Matt Spinler963c65f2018-11-26 14:46:41 -06009#include <xyz/openbmc_project/State/Chassis/server.hpp>
10#include <xyz/openbmc_project/State/Host/server.hpp>
Rush Chen31ce3752024-11-08 14:57:27 +080011
12#include <fstream>
13#include <iostream>
14#include <string>
15
Matt Spinlerfb35a322018-11-26 14:30:30 -060016namespace phosphor
17{
18namespace button
19{
Matt Spinler963c65f2018-11-26 14:46:41 -060020
21namespace sdbusRule = sdbusplus::bus::match::rules;
22using namespace sdbusplus::xyz::openbmc_project::State::server;
Rush Chen31ce3752024-11-08 14:57:27 +080023using namespace sdbusplus::xyz::openbmc_project::Chassis::Buttons::server;
Liora Guofbd3bd52025-10-09 16:47:52 +080024using GetSubTreePathsType = std::vector<std::string>;
Rush Chen31ce3752024-11-08 14:57:27 +080025
26const std::map<std::string, Chassis::Transition> chassisPwrCtls = {
27 {"chassis-on", Chassis::Transition::On},
28 {"chassis-off", Chassis::Transition::Off},
29 {"chassis-cycle", Chassis::Transition::PowerCycle}};
Matt Spinler963c65f2018-11-26 14:46:41 -060030
Matt Spinler963c65f2018-11-26 14:46:41 -060031constexpr auto chassisIface = "xyz.openbmc_project.State.Chassis";
32constexpr auto hostIface = "xyz.openbmc_project.State.Host";
33constexpr auto powerButtonIface = "xyz.openbmc_project.Chassis.Buttons.Power";
Matt Spinler69f93512018-11-26 14:55:58 -060034constexpr auto idButtonIface = "xyz.openbmc_project.Chassis.Buttons.ID";
Matt Spinler06a5bdd2018-11-26 14:50:48 -060035constexpr auto resetButtonIface = "xyz.openbmc_project.Chassis.Buttons.Reset";
Matt Spinler69f93512018-11-26 14:55:58 -060036constexpr auto ledGroupIface = "xyz.openbmc_project.Led.Group";
Naveen Moses3bd1cfc2022-02-14 18:04:20 +053037constexpr auto ledGroupBasePath = "/xyz/openbmc_project/led/groups/";
38constexpr auto hostSelectorIface =
39 "xyz.openbmc_project.Chassis.Buttons.HostSelector";
40constexpr auto debugHostSelectorIface =
Naveen Mosesa6d4e652022-04-13 19:27:25 +053041 "xyz.openbmc_project.Chassis.Buttons.Button";
Naveen Moses3bd1cfc2022-02-14 18:04:20 +053042
43constexpr auto propertyIface = "org.freedesktop.DBus.Properties";
44constexpr auto mapperIface = "xyz.openbmc_project.ObjectMapper";
Matt Spinler963c65f2018-11-26 14:46:41 -060045
46constexpr auto mapperObjPath = "/xyz/openbmc_project/object_mapper";
47constexpr auto mapperService = "xyz.openbmc_project.ObjectMapper";
Naveen Moses3bd1cfc2022-02-14 18:04:20 +053048constexpr auto BMC_POSITION = 0;
Matt Spinler963c65f2018-11-26 14:46:41 -060049
Rush Chen31ce3752024-11-08 14:57:27 +080050std::vector<std::map<uint16_t, Chassis::Transition>> multiPwrBtnActConf;
51
Patrick Williams9a529a62022-07-22 19:26:54 -050052Handler::Handler(sdbusplus::bus_t& bus) : bus(bus)
Matt Spinlerfb35a322018-11-26 14:30:30 -060053{
Rush Chen31ce3752024-11-08 14:57:27 +080054 /* So far, there are two modes for multi-host power control
55 - host select button mode, e.g.: Yosemite V2
56 only one power button with host select switch,
57 which's interface for handling target host,
58 in the case, hostSelectButtonMode = true
59 - multi power button mode, e.g.: Greatlakes
60 each slot/sled has its own power button,
61 in the case, hostSelectButtonMode = false */
Rush Chen31ce3752024-11-08 14:57:27 +080062
63 std::ifstream gpios{gpioDefFile};
64 auto configDefJson = nlohmann::json::parse(gpios, nullptr, true);
65 nlohmann::json gpioDefs = configDefJson["gpio_definitions"];
66
Liora Guofbd3bd52025-10-09 16:47:52 +080067 bool isHostSelectorExists =
68 !getService(HS_DBUS_OBJECT_NAME, hostSelectorIface).empty();
69
Rush Chen31ce3752024-11-08 14:57:27 +080070 for (const auto& gpioConfig : gpioDefs)
71 {
72 if (gpioConfig.contains("multi-action"))
73 {
74 std::map<uint16_t, Chassis::Transition> mapEntry;
75 const auto& multiActCfg = gpioConfig["multi-action"];
76 for (const auto& ActCfg : multiActCfg)
77 {
78 auto chassisPwrCtl = chassisPwrCtls.find(ActCfg["action"]);
79 if (chassisPwrCtl != chassisPwrCtls.end())
80 {
81 auto duration = ActCfg["duration"].get<uint16_t>();
82 mapEntry[duration] = chassisPwrCtl->second;
83 }
84 else
85 {
86 lg2::error("unknown power button action");
87 }
88 }
89 multiPwrBtnActConf.emplace_back(mapEntry);
90 }
Liora Guofbd3bd52025-10-09 16:47:52 +080091
92 if (gpioConfig.value("name", "") == "HOST_SELECTOR")
Rush Chen31ce3752024-11-08 14:57:27 +080093 {
Liora Guofbd3bd52025-10-09 16:47:52 +080094 virtualButton = gpioConfig.value("virtual_button", false);
95 lg2::debug("Change virtualButton flag to: {VIRTUAL}", "VIRTUAL",
96 virtualButton);
Rush Chen31ce3752024-11-08 14:57:27 +080097 }
98 }
99
Liora Guofbd3bd52025-10-09 16:47:52 +0800100 hostSelectButtonMode = isHostSelectorExists && !virtualButton;
101 lg2::debug("hostSelectButtonMode: {MODE}", "MODE", hostSelectButtonMode);
102
Matt Spinler963c65f2018-11-26 14:46:41 -0600103 try
104 {
Liora Guofbd3bd52025-10-09 16:47:52 +0800105 static const int depth = 1;
106 GetSubTreePathsType powerButtonSubTreePaths;
107 auto method = bus.new_method_call(mapperService, mapperObjPath,
108 mapperIface, "GetSubTreePaths");
109 method.append("/xyz/openbmc_project/Chassis/Buttons", depth,
110 GetSubTreePathsType({powerButtonIface}));
111 auto reply = bus.call(method);
112 reply.read(powerButtonSubTreePaths);
113 if (!powerButtonSubTreePaths.empty())
Matt Spinler963c65f2018-11-26 14:46:41 -0600114 {
George Liu9fb15972022-06-20 14:54:38 +0800115 lg2::info("Starting power button handler");
Matt Spinler1a309f72023-04-04 13:12:19 -0500116
117 // Check for a custom handler
118 powerButtonProfile =
119 PowerButtonProfileFactory::instance().createProfile(bus);
120
Liora Guofbd3bd52025-10-09 16:47:52 +0800121 // Fallback: register for all power buttons found
Matt Spinler1a309f72023-04-04 13:12:19 -0500122 if (!powerButtonProfile)
123 {
Liora Guofbd3bd52025-10-09 16:47:52 +0800124 for (const auto& path : powerButtonSubTreePaths)
125 {
126 lg2::debug("Registering power button handler for: {PATH}",
127 "PATH", path);
128 std::unique_ptr<sdbusplus::bus::match_t>
129 multiPowerReleaseMatch =
130 std::make_unique<sdbusplus::bus::match_t>(
131 bus,
132 sdbusRule::type::signal() +
133 sdbusRule::member("Released") +
134 sdbusRule::path(path) +
135 sdbusRule::interface(powerButtonIface),
136 std::bind(std::mem_fn(&Handler::powerReleased),
137 this, std::placeholders::_1));
138 multiPowerButtonReleased.emplace_back(
139 std::move(multiPowerReleaseMatch));
140 }
Rush Chen31ce3752024-11-08 14:57:27 +0800141 }
142 }
Matt Spinler963c65f2018-11-26 14:46:41 -0600143 }
Patrick Williams9a529a62022-07-22 19:26:54 -0500144 catch (const sdbusplus::exception_t& e)
Matt Spinler963c65f2018-11-26 14:46:41 -0600145 {
Liora Guofbd3bd52025-10-09 16:47:52 +0800146 lg2::error("Error creating power button handlers: '{ERROR_MESSAGE}'",
147 "ERROR_MESSAGE", e.what());
Matt Spinler963c65f2018-11-26 14:46:41 -0600148 }
Matt Spinler06a5bdd2018-11-26 14:50:48 -0600149
150 try
151 {
Matt Spinler69f93512018-11-26 14:55:58 -0600152 if (!getService(ID_DBUS_OBJECT_NAME, idButtonIface).empty())
153 {
George Liu9fb15972022-06-20 14:54:38 +0800154 lg2::info("Registering ID button handler");
Matt Spinler69f93512018-11-26 14:55:58 -0600155 idButtonReleased = std::make_unique<sdbusplus::bus::match_t>(
156 bus,
157 sdbusRule::type::signal() + sdbusRule::member("Released") +
158 sdbusRule::path(ID_DBUS_OBJECT_NAME) +
159 sdbusRule::interface(idButtonIface),
Naveen Mosesab8dac52022-07-15 19:32:27 +0530160 std::bind(std::mem_fn(&Handler::idReleased), this,
Matt Spinler69f93512018-11-26 14:55:58 -0600161 std::placeholders::_1));
162 }
163 }
Patrick Williams9a529a62022-07-22 19:26:54 -0500164 catch (const sdbusplus::exception_t& e)
Matt Spinler69f93512018-11-26 14:55:58 -0600165 {
166 // The button wasn't implemented
167 }
168
169 try
170 {
Matt Spinler06a5bdd2018-11-26 14:50:48 -0600171 if (!getService(RESET_DBUS_OBJECT_NAME, resetButtonIface).empty())
172 {
George Liu9fb15972022-06-20 14:54:38 +0800173 lg2::info("Registering reset button handler");
Matt Spinler06a5bdd2018-11-26 14:50:48 -0600174 resetButtonReleased = std::make_unique<sdbusplus::bus::match_t>(
175 bus,
176 sdbusRule::type::signal() + sdbusRule::member("Released") +
177 sdbusRule::path(RESET_DBUS_OBJECT_NAME) +
178 sdbusRule::interface(resetButtonIface),
Naveen Mosesab8dac52022-07-15 19:32:27 +0530179 std::bind(std::mem_fn(&Handler::resetReleased), this,
Matt Spinler06a5bdd2018-11-26 14:50:48 -0600180 std::placeholders::_1));
181 }
182 }
Patrick Williams9a529a62022-07-22 19:26:54 -0500183 catch (const sdbusplus::exception_t& e)
Matt Spinler06a5bdd2018-11-26 14:50:48 -0600184 {
185 // The button wasn't implemented
186 }
Naveen Mosesa6d4e652022-04-13 19:27:25 +0530187 try
188 {
189 if (!getService(DBG_HS_DBUS_OBJECT_NAME, debugHostSelectorIface)
190 .empty())
191 {
192 lg2::info("Registering debug host selector button handler");
193 debugHSButtonReleased = std::make_unique<sdbusplus::bus::match_t>(
194 bus,
195 sdbusRule::type::signal() + sdbusRule::member("Released") +
196 sdbusRule::path(DBG_HS_DBUS_OBJECT_NAME) +
197 sdbusRule::interface(debugHostSelectorIface),
198 std::bind(std::mem_fn(&Handler::debugHostSelectorReleased),
199 this, std::placeholders::_1));
200 }
201 }
Patrick Williamse3b4e112022-11-26 09:41:58 -0600202 catch (const sdbusplus::exception_t& e)
Naveen Mosesa6d4e652022-04-13 19:27:25 +0530203 {
204 // The button wasn't implemented
205 }
Matt Spinler963c65f2018-11-26 14:46:41 -0600206}
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530207bool Handler::isMultiHost()
208{
Rush Chen31ce3752024-11-08 14:57:27 +0800209 if (numberOfChassis() != 1)
210 {
211 return true;
212 }
213 else
214 {
215 return (hostSelectButtonMode);
216 }
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530217}
Matt Spinler963c65f2018-11-26 14:46:41 -0600218std::string Handler::getService(const std::string& path,
219 const std::string& interface) const
220{
221 auto method = bus.new_method_call(mapperService, mapperObjPath, mapperIface,
222 "GetObject");
223 method.append(path, std::vector{interface});
Thang Q. Nguyen42507852022-08-12 09:11:35 +0700224 try
225 {
226 auto result = bus.call(method);
Patrick Williams60dc3412025-11-05 00:05:37 -0500227 auto objectData =
228 result.unpack<std::map<std::string, std::vector<std::string>>>();
229
Thang Q. Nguyen42507852022-08-12 09:11:35 +0700230 return objectData.begin()->first;
231 }
Patrick Williamse3b4e112022-11-26 09:41:58 -0600232 catch (const sdbusplus::exception_t& e)
Thang Q. Nguyen42507852022-08-12 09:11:35 +0700233 {
234 return std::string();
235 }
Matt Spinler963c65f2018-11-26 14:46:41 -0600236}
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530237size_t Handler::getHostSelectorValue()
Matt Spinler963c65f2018-11-26 14:46:41 -0600238{
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530239 auto HSService = getService(HS_DBUS_OBJECT_NAME, hostSelectorIface);
240
241 if (HSService.empty())
242 {
Naveen Mosesa6d4e652022-04-13 19:27:25 +0530243 lg2::info("Host selector dbus object not available");
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530244 throw std::invalid_argument("Host selector dbus object not available");
245 }
246
247 try
248 {
249 auto method = bus.new_method_call(
250 HSService.c_str(), HS_DBUS_OBJECT_NAME, propertyIface, "Get");
251 method.append(hostSelectorIface, "Position");
252 auto result = bus.call(method);
253
Patrick Williams60dc3412025-11-05 00:05:37 -0500254 auto HSPositionVariant = result.unpack<std::variant<size_t>>();
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530255
256 auto position = std::get<size_t>(HSPositionVariant);
257 return position;
258 }
Patrick Williams9a529a62022-07-22 19:26:54 -0500259 catch (const sdbusplus::exception_t& e)
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530260 {
Naveen Mosesa6d4e652022-04-13 19:27:25 +0530261 lg2::error("Error reading host selector position: {ERROR}", "ERROR", e);
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530262 throw;
263 }
264}
265bool Handler::poweredOn(size_t hostNumber) const
266{
Potin Laic0fee462022-12-23 14:19:23 +0800267 auto hostObjectName = HOST_STATE_OBJECT_NAME + std::to_string(hostNumber);
268 auto service = getService(hostObjectName.c_str(), hostIface);
269 auto method = bus.new_method_call(service.c_str(), hostObjectName.c_str(),
270 propertyIface, "Get");
271 method.append(hostIface, "CurrentHostState");
Matt Spinler963c65f2018-11-26 14:46:41 -0600272 auto result = bus.call(method);
273
Patrick Williams60dc3412025-11-05 00:05:37 -0500274 auto state = result.unpack<std::variant<std::string>>();
Matt Spinler963c65f2018-11-26 14:46:41 -0600275
Potin Laic0fee462022-12-23 14:19:23 +0800276 return Host::HostState::Off !=
277 Host::convertHostStateFromString(std::get<std::string>(state));
Matt Spinler963c65f2018-11-26 14:46:41 -0600278}
279
DelphineCCChiu395c7642023-04-19 10:46:47 +0800280void Handler::handlePowerEvent(PowerEvent powerEventType,
Rush Chen31ce3752024-11-08 14:57:27 +0800281 const std::string& objectPath,
DelphineCCChiu395c7642023-04-19 10:46:47 +0800282 std::chrono::microseconds duration)
Matt Spinler963c65f2018-11-26 14:46:41 -0600283{
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530284 std::string objPathName;
285 std::string dbusIfaceName;
286 std::string transitionName;
287 std::variant<Host::Transition, Chassis::Transition> transition;
Matt Spinler963c65f2018-11-26 14:46:41 -0600288
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530289 size_t hostNumber = 0;
Rush Chen31ce3752024-11-08 14:57:27 +0800290 std::string hostNumStr =
291 objectPath.substr(std::string(POWER_DBUS_OBJECT_NAME).length());
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530292 auto isMultiHostSystem = isMultiHost();
Rush Chen31ce3752024-11-08 14:57:27 +0800293
294 if (hostSelectButtonMode)
Matt Spinler963c65f2018-11-26 14:46:41 -0600295 {
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530296 hostNumber = getHostSelectorValue();
Naveen Mosesa6d4e652022-04-13 19:27:25 +0530297 lg2::info("Multi-host system detected : {POSITION}", "POSITION",
George Liu9fb15972022-06-20 14:54:38 +0800298 hostNumber);
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530299
Rush Chen31ce3752024-11-08 14:57:27 +0800300 hostNumStr = std::to_string(hostNumber);
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530301
Rush Chen31ce3752024-11-08 14:57:27 +0800302 // ignore power and reset button events if BMC is selected.
303 if (isMultiHostSystem && (hostNumber == BMC_POSITION) &&
304 (powerEventType != PowerEvent::powerReleased) &&
305 (duration <= LONG_PRESS_TIME_MS))
306 {
307 lg2::info(
308 "handlePowerEvent : BMC selected on multi-host system. ignoring power and reset button events...");
309 return;
310 }
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530311 }
312
313 switch (powerEventType)
314 {
Naveen Mosesab8dac52022-07-15 19:32:27 +0530315 case PowerEvent::powerReleased:
George Liu5b98f4d2022-06-20 13:31:14 +0800316 {
Rush Chen31ce3752024-11-08 14:57:27 +0800317 for (const auto& iter : multiPwrBtnActConf[stoi(hostNumStr) - 1])
318 {
319 if (duration > std::chrono::milliseconds(iter.first))
320 {
321 dbusIfaceName = chassisIface;
322 transitionName = "RequestedPowerTransition";
323 objPathName = CHASSIS_STATE_OBJECT_NAME + hostNumStr;
324 transition = iter.second;
325 }
326 }
327 break;
328
Patrick Williams971312a2024-04-12 13:45:50 -0500329 if (duration <= LONG_PRESS_TIME_MS)
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530330 {
DelphineCCChiu395c7642023-04-19 10:46:47 +0800331 objPathName = HOST_STATE_OBJECT_NAME + hostNumStr;
332 dbusIfaceName = hostIface;
333 transitionName = "RequestedHostTransition";
334
335 transition = Host::Transition::On;
336
337 if (poweredOn(hostNumber))
338 {
339 transition = Host::Transition::Off;
340 }
341 lg2::info("handlePowerEvent : Handle power button press ");
DelphineCCChiu395c7642023-04-19 10:46:47 +0800342 break;
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530343 }
DelphineCCChiu395c7642023-04-19 10:46:47 +0800344 else
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530345 {
DelphineCCChiu395c7642023-04-19 10:46:47 +0800346 dbusIfaceName = chassisIface;
347 transitionName = "RequestedPowerTransition";
348 objPathName = CHASSIS_STATE_OBJECT_NAME + hostNumStr;
349 transition = Chassis::Transition::Off;
350
351 /* multi host system :
352 hosts (1 to N) - host shutdown
353 bmc (0) - sled cycle
354 single host system :
355 host(0) - host shutdown
356 */
357 if (isMultiHostSystem && (hostNumber == BMC_POSITION))
358 {
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530359#if CHASSIS_SYSTEM_RESET_ENABLED
DelphineCCChiu395c7642023-04-19 10:46:47 +0800360 objPathName = CHASSISSYSTEM_STATE_OBJECT_NAME + hostNumStr;
361 transition = Chassis::Transition::PowerCycle;
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530362#else
DelphineCCChiu395c7642023-04-19 10:46:47 +0800363 return;
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530364#endif
DelphineCCChiu395c7642023-04-19 10:46:47 +0800365 }
366 else if (!poweredOn(hostNumber))
367 {
368 lg2::info(
369 "Power is off so ignoring long power button press");
370 return;
371 }
372 lg2::info("handlePowerEvent : handle long power button press");
373 break;
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530374 }
Matt Spinler963c65f2018-11-26 14:46:41 -0600375 }
Naveen Mosesab8dac52022-07-15 19:32:27 +0530376 case PowerEvent::resetReleased:
George Liu5b98f4d2022-06-20 13:31:14 +0800377 {
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530378 objPathName = HOST_STATE_OBJECT_NAME + hostNumStr;
379 dbusIfaceName = hostIface;
380 transitionName = "RequestedHostTransition";
Matt Spinler963c65f2018-11-26 14:46:41 -0600381
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530382 if (!poweredOn(hostNumber))
383 {
George Liu9fb15972022-06-20 14:54:38 +0800384 lg2::info("Power is off so ignoring reset button press");
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530385 return;
386 }
Matt Spinler963c65f2018-11-26 14:46:41 -0600387
George Liu9fb15972022-06-20 14:54:38 +0800388 lg2::info("Handling reset button press");
HuyLe9456ffc2023-06-22 15:21:22 +0700389#ifdef ENABLE_RESET_BUTTON_DO_WARM_REBOOT
390 transition = Host::Transition::ForceWarmReboot;
391#else
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530392 transition = Host::Transition::Reboot;
HuyLe9456ffc2023-06-22 15:21:22 +0700393#endif
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530394 break;
395 }
George Liu5b98f4d2022-06-20 13:31:14 +0800396 default:
397 {
George Liu9fb15972022-06-20 14:54:38 +0800398 lg2::error("{EVENT} is invalid power event. skipping...", "EVENT",
Patrick Williams36106082024-02-26 10:26:43 -0600399 powerEventType);
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530400
401 return;
402 }
403 }
404 auto service = getService(objPathName.c_str(), dbusIfaceName);
405 auto method = bus.new_method_call(service.c_str(), objPathName.c_str(),
406 propertyIface, "Set");
407 method.append(dbusIfaceName, transitionName, transition);
408 bus.call(method);
409}
Rush Chen31ce3752024-11-08 14:57:27 +0800410
DelphineCCChiu395c7642023-04-19 10:46:47 +0800411void Handler::powerReleased(sdbusplus::message_t& msg)
Naveen Moses3bd1cfc2022-02-14 18:04:20 +0530412{
413 try
414 {
Patrick Williams60dc3412025-11-05 00:05:37 -0500415 auto time = msg.unpack<uint64_t>();
DelphineCCChiu395c7642023-04-19 10:46:47 +0800416
Rush Chen31ce3752024-11-08 14:57:27 +0800417 handlePowerEvent(PowerEvent::powerReleased, msg.get_path(),
DelphineCCChiu395c7642023-04-19 10:46:47 +0800418 std::chrono::microseconds(time));
Matt Spinler963c65f2018-11-26 14:46:41 -0600419 }
Patrick Williams9a529a62022-07-22 19:26:54 -0500420 catch (const sdbusplus::exception_t& e)
Matt Spinler963c65f2018-11-26 14:46:41 -0600421 {
George Liu9fb15972022-06-20 14:54:38 +0800422 lg2::error("Failed power state change on a power button press: {ERROR}",
423 "ERROR", e);
Matt Spinler963c65f2018-11-26 14:46:41 -0600424 }
425}
Matt Spinler06a5bdd2018-11-26 14:50:48 -0600426
Rush Chen31ce3752024-11-08 14:57:27 +0800427void Handler::resetReleased(sdbusplus::message_t& msg)
Matt Spinler06a5bdd2018-11-26 14:50:48 -0600428{
429 try
430 {
DelphineCCChiu395c7642023-04-19 10:46:47 +0800431 // No need to calculate duration, set to 0.
Rush Chen31ce3752024-11-08 14:57:27 +0800432 handlePowerEvent(PowerEvent::resetReleased, msg.get_path(),
DelphineCCChiu395c7642023-04-19 10:46:47 +0800433 std::chrono::microseconds(0));
Matt Spinler06a5bdd2018-11-26 14:50:48 -0600434 }
Patrick Williams9a529a62022-07-22 19:26:54 -0500435 catch (const sdbusplus::exception_t& e)
Matt Spinler06a5bdd2018-11-26 14:50:48 -0600436 {
George Liu9fb15972022-06-20 14:54:38 +0800437 lg2::error("Failed power state change on a reset button press: {ERROR}",
438 "ERROR", e);
Matt Spinler06a5bdd2018-11-26 14:50:48 -0600439 }
440}
Matt Spinler69f93512018-11-26 14:55:58 -0600441
Patrick Williams9a529a62022-07-22 19:26:54 -0500442void Handler::idReleased(sdbusplus::message_t& /* msg */)
Matt Spinler69f93512018-11-26 14:55:58 -0600443{
444 std::string groupPath{ledGroupBasePath};
445 groupPath += ID_LED_GROUP;
446
447 auto service = getService(groupPath, ledGroupIface);
448
449 if (service.empty())
450 {
George Liu9fb15972022-06-20 14:54:38 +0800451 lg2::info("No found {GROUP} during ID button press:", "GROUP",
452 groupPath);
Matt Spinler69f93512018-11-26 14:55:58 -0600453 return;
454 }
455
456 try
457 {
458 auto method = bus.new_method_call(service.c_str(), groupPath.c_str(),
459 propertyIface, "Get");
460 method.append(ledGroupIface, "Asserted");
461 auto result = bus.call(method);
462
Patrick Williams60dc3412025-11-05 00:05:37 -0500463 auto state = result.unpack<std::variant<bool>>();
Matt Spinler69f93512018-11-26 14:55:58 -0600464
Patrick Williams51f5e8b2020-05-13 11:33:44 -0500465 state = !std::get<bool>(state);
Matt Spinler69f93512018-11-26 14:55:58 -0600466
George Liu9fb15972022-06-20 14:54:38 +0800467 lg2::info(
468 "Changing ID LED group state on ID LED press, GROUP = {GROUP}, STATE = {STATE}",
469 "GROUP", groupPath, "STATE", std::get<bool>(state));
Matt Spinler69f93512018-11-26 14:55:58 -0600470
471 method = bus.new_method_call(service.c_str(), groupPath.c_str(),
472 propertyIface, "Set");
473
474 method.append(ledGroupIface, "Asserted", state);
475 result = bus.call(method);
476 }
Patrick Williams9a529a62022-07-22 19:26:54 -0500477 catch (const sdbusplus::exception_t& e)
Matt Spinler69f93512018-11-26 14:55:58 -0600478 {
George Liu9fb15972022-06-20 14:54:38 +0800479 lg2::error("Error toggling ID LED group on ID button press: {ERROR}",
480 "ERROR", e);
Matt Spinler69f93512018-11-26 14:55:58 -0600481 }
482}
Naveen Mosesa6d4e652022-04-13 19:27:25 +0530483
484void Handler::increaseHostSelectorPosition()
485{
486 try
487 {
488 auto HSService = getService(HS_DBUS_OBJECT_NAME, hostSelectorIface);
489
490 if (HSService.empty())
491 {
492 lg2::error("Host selector service not available");
493 return;
494 }
495
496 auto method =
497 bus.new_method_call(HSService.c_str(), HS_DBUS_OBJECT_NAME,
498 phosphor::button::propertyIface, "GetAll");
499 method.append(phosphor::button::hostSelectorIface);
500 auto result = bus.call(method);
Patrick Williams60dc3412025-11-05 00:05:37 -0500501 auto properties = result.unpack<
502 std::unordered_map<std::string, std::variant<size_t>>>();
Naveen Mosesa6d4e652022-04-13 19:27:25 +0530503
504 auto maxPosition = std::get<size_t>(properties.at("MaxPosition"));
505 auto position = std::get<size_t>(properties.at("Position"));
506
507 std::variant<size_t> HSPositionVariant =
508 (position < maxPosition) ? (position + 1) : 0;
509
510 method = bus.new_method_call(HSService.c_str(), HS_DBUS_OBJECT_NAME,
511 phosphor::button::propertyIface, "Set");
512 method.append(phosphor::button::hostSelectorIface, "Position");
513
514 method.append(HSPositionVariant);
515 result = bus.call(method);
516 }
Patrick Williamse3b4e112022-11-26 09:41:58 -0600517 catch (const sdbusplus::exception_t& e)
Naveen Mosesa6d4e652022-04-13 19:27:25 +0530518 {
519 lg2::error("Error modifying host selector position : {ERROR}", "ERROR",
520 e);
521 }
522}
523
Patrick Williamse3b4e112022-11-26 09:41:58 -0600524void Handler::debugHostSelectorReleased(sdbusplus::message_t& /* msg */)
Naveen Mosesa6d4e652022-04-13 19:27:25 +0530525{
526 try
527 {
528 increaseHostSelectorPosition();
529 }
Patrick Williamse3b4e112022-11-26 09:41:58 -0600530 catch (const sdbusplus::exception_t& e)
Naveen Mosesa6d4e652022-04-13 19:27:25 +0530531 {
532 lg2::error(
533 "Failed power process debug host selector button press : {ERROR}",
534 "ERROR", e);
535 }
536}
537
Matt Spinlerfb35a322018-11-26 14:30:30 -0600538} // namespace button
539} // namespace phosphor