blob: 6362f827c81fb830dd722fea3386902d05f50a8e [file] [log] [blame]
Matt Spinlerfb35a322018-11-26 14:30:30 -06001#include "button_handler.hpp"
2
Matt Spinler69f93512018-11-26 14:55:58 -06003#include "settings.hpp"
4
Matt Spinler963c65f2018-11-26 14:46:41 -06005#include <phosphor-logging/log.hpp>
6#include <xyz/openbmc_project/State/Chassis/server.hpp>
7#include <xyz/openbmc_project/State/Host/server.hpp>
8
Matt Spinlerfb35a322018-11-26 14:30:30 -06009namespace phosphor
10{
11namespace button
12{
Matt Spinler963c65f2018-11-26 14:46:41 -060013
14namespace sdbusRule = sdbusplus::bus::match::rules;
15using namespace sdbusplus::xyz::openbmc_project::State::server;
16using namespace phosphor::logging;
Matt Spinler963c65f2018-11-26 14:46:41 -060017
18constexpr auto propertyIface = "org.freedesktop.DBus.Properties";
19constexpr auto chassisIface = "xyz.openbmc_project.State.Chassis";
20constexpr auto hostIface = "xyz.openbmc_project.State.Host";
21constexpr auto powerButtonIface = "xyz.openbmc_project.Chassis.Buttons.Power";
Matt Spinler69f93512018-11-26 14:55:58 -060022constexpr auto idButtonIface = "xyz.openbmc_project.Chassis.Buttons.ID";
Matt Spinler06a5bdd2018-11-26 14:50:48 -060023constexpr auto resetButtonIface = "xyz.openbmc_project.Chassis.Buttons.Reset";
Matt Spinler963c65f2018-11-26 14:46:41 -060024constexpr auto mapperIface = "xyz.openbmc_project.ObjectMapper";
Matt Spinler69f93512018-11-26 14:55:58 -060025constexpr auto ledGroupIface = "xyz.openbmc_project.Led.Group";
Matt Spinler963c65f2018-11-26 14:46:41 -060026
27constexpr auto mapperObjPath = "/xyz/openbmc_project/object_mapper";
28constexpr auto mapperService = "xyz.openbmc_project.ObjectMapper";
Matt Spinler69f93512018-11-26 14:55:58 -060029constexpr auto ledGroupBasePath = "/xyz/openbmc_project/led/groups/";
Matt Spinler963c65f2018-11-26 14:46:41 -060030
Matt Spinlerfb35a322018-11-26 14:30:30 -060031Handler::Handler(sdbusplus::bus::bus& bus) : bus(bus)
32{
Matt Spinler963c65f2018-11-26 14:46:41 -060033 try
34 {
35 if (!getService(POWER_DBUS_OBJECT_NAME, powerButtonIface).empty())
36 {
37 log<level::INFO>("Starting power button handler");
38 powerButtonReleased = std::make_unique<sdbusplus::bus::match_t>(
39 bus,
40 sdbusRule::type::signal() + sdbusRule::member("Released") +
41 sdbusRule::path(POWER_DBUS_OBJECT_NAME) +
42 sdbusRule::interface(powerButtonIface),
43 std::bind(std::mem_fn(&Handler::powerPressed), this,
44 std::placeholders::_1));
45
46 powerButtonLongPressReleased =
47 std::make_unique<sdbusplus::bus::match_t>(
48 bus,
49 sdbusRule::type::signal() +
50 sdbusRule::member("PressedLong") +
51 sdbusRule::path(POWER_DBUS_OBJECT_NAME) +
52 sdbusRule::interface(powerButtonIface),
53 std::bind(std::mem_fn(&Handler::longPowerPressed), this,
54 std::placeholders::_1));
55 }
56 }
Patrick Williams6d724ce2021-10-06 12:40:26 -050057 catch (const sdbusplus::exception::exception& e)
Matt Spinler963c65f2018-11-26 14:46:41 -060058 {
59 // The button wasn't implemented
60 }
Matt Spinler06a5bdd2018-11-26 14:50:48 -060061
62 try
63 {
Matt Spinler69f93512018-11-26 14:55:58 -060064 if (!getService(ID_DBUS_OBJECT_NAME, idButtonIface).empty())
65 {
66 log<level::INFO>("Registering ID button handler");
67 idButtonReleased = std::make_unique<sdbusplus::bus::match_t>(
68 bus,
69 sdbusRule::type::signal() + sdbusRule::member("Released") +
70 sdbusRule::path(ID_DBUS_OBJECT_NAME) +
71 sdbusRule::interface(idButtonIface),
72 std::bind(std::mem_fn(&Handler::idPressed), this,
73 std::placeholders::_1));
74 }
75 }
Patrick Williams6d724ce2021-10-06 12:40:26 -050076 catch (const sdbusplus::exception::exception& e)
Matt Spinler69f93512018-11-26 14:55:58 -060077 {
78 // The button wasn't implemented
79 }
80
81 try
82 {
Matt Spinler06a5bdd2018-11-26 14:50:48 -060083 if (!getService(RESET_DBUS_OBJECT_NAME, resetButtonIface).empty())
84 {
85 log<level::INFO>("Registering reset button handler");
86 resetButtonReleased = std::make_unique<sdbusplus::bus::match_t>(
87 bus,
88 sdbusRule::type::signal() + sdbusRule::member("Released") +
89 sdbusRule::path(RESET_DBUS_OBJECT_NAME) +
90 sdbusRule::interface(resetButtonIface),
91 std::bind(std::mem_fn(&Handler::resetPressed), this,
92 std::placeholders::_1));
93 }
94 }
Patrick Williams6d724ce2021-10-06 12:40:26 -050095 catch (const sdbusplus::exception::exception& e)
Matt Spinler06a5bdd2018-11-26 14:50:48 -060096 {
97 // The button wasn't implemented
98 }
Matt Spinler963c65f2018-11-26 14:46:41 -060099}
100
101std::string Handler::getService(const std::string& path,
102 const std::string& interface) const
103{
104 auto method = bus.new_method_call(mapperService, mapperObjPath, mapperIface,
105 "GetObject");
106 method.append(path, std::vector{interface});
107 auto result = bus.call(method);
108
109 std::map<std::string, std::vector<std::string>> objectData;
110 result.read(objectData);
111
112 return objectData.begin()->first;
113}
114
115bool Handler::poweredOn() const
116{
117 auto service = getService(CHASSIS_STATE_OBJECT_NAME, chassisIface);
118 auto method = bus.new_method_call(
119 service.c_str(), CHASSIS_STATE_OBJECT_NAME, propertyIface, "Get");
120 method.append(chassisIface, "CurrentPowerState");
121 auto result = bus.call(method);
122
Patrick Williams5ed4cc02020-05-13 17:52:15 -0500123 std::variant<std::string> state;
Matt Spinler963c65f2018-11-26 14:46:41 -0600124 result.read(state);
125
126 return Chassis::PowerState::On ==
Patrick Williams51f5e8b2020-05-13 11:33:44 -0500127 Chassis::convertPowerStateFromString(std::get<std::string>(state));
Matt Spinler963c65f2018-11-26 14:46:41 -0600128}
129
130void Handler::powerPressed(sdbusplus::message::message& msg)
131{
132 auto transition = Host::Transition::On;
133
134 try
135 {
136 if (poweredOn())
137 {
138 transition = Host::Transition::Off;
139 }
140
141 log<level::INFO>("Handling power button press");
142
Patrick Williams5ed4cc02020-05-13 17:52:15 -0500143 std::variant<std::string> state = convertForMessage(transition);
Matt Spinler963c65f2018-11-26 14:46:41 -0600144
145 auto service = getService(HOST_STATE_OBJECT_NAME, hostIface);
146 auto method = bus.new_method_call(
147 service.c_str(), HOST_STATE_OBJECT_NAME, propertyIface, "Set");
148 method.append(hostIface, "RequestedHostTransition", state);
149
150 bus.call(method);
151 }
Patrick Williams6d724ce2021-10-06 12:40:26 -0500152 catch (const sdbusplus::exception::exception& e)
Matt Spinler963c65f2018-11-26 14:46:41 -0600153 {
154 log<level::ERR>("Failed power state change on a power button press",
155 entry("ERROR=%s", e.what()));
156 }
157}
158
159void Handler::longPowerPressed(sdbusplus::message::message& msg)
160{
161 try
162 {
163 if (!poweredOn())
164 {
165 log<level::INFO>(
166 "Power is off so ignoring long power button press");
167 return;
168 }
169
170 log<level::INFO>("Handling long power button press");
171
Patrick Williams5ed4cc02020-05-13 17:52:15 -0500172 std::variant<std::string> state =
Matt Spinler963c65f2018-11-26 14:46:41 -0600173 convertForMessage(Chassis::Transition::Off);
174
175 auto service = getService(CHASSIS_STATE_OBJECT_NAME, chassisIface);
176 auto method = bus.new_method_call(
177 service.c_str(), CHASSIS_STATE_OBJECT_NAME, propertyIface, "Set");
178 method.append(chassisIface, "RequestedPowerTransition", state);
179
180 bus.call(method);
181 }
Patrick Williams6d724ce2021-10-06 12:40:26 -0500182 catch (const sdbusplus::exception::exception& e)
Matt Spinler963c65f2018-11-26 14:46:41 -0600183 {
184 log<level::ERR>("Failed powering off on long power button press",
185 entry("ERROR=%s", e.what()));
186 }
Matt Spinlerfb35a322018-11-26 14:30:30 -0600187}
Matt Spinler06a5bdd2018-11-26 14:50:48 -0600188
189void Handler::resetPressed(sdbusplus::message::message& msg)
190{
191 try
192 {
193 if (!poweredOn())
194 {
195 log<level::INFO>("Power is off so ignoring reset button press");
196 return;
197 }
198
199 log<level::INFO>("Handling reset button press");
200
Patrick Williams5ed4cc02020-05-13 17:52:15 -0500201 std::variant<std::string> state =
Matt Spinler06a5bdd2018-11-26 14:50:48 -0600202 convertForMessage(Host::Transition::Reboot);
203
204 auto service = getService(HOST_STATE_OBJECT_NAME, hostIface);
205 auto method = bus.new_method_call(
206 service.c_str(), HOST_STATE_OBJECT_NAME, propertyIface, "Set");
207
208 method.append(hostIface, "RequestedHostTransition", state);
209
210 bus.call(method);
211 }
Patrick Williams6d724ce2021-10-06 12:40:26 -0500212 catch (const sdbusplus::exception::exception& e)
Matt Spinler06a5bdd2018-11-26 14:50:48 -0600213 {
214 log<level::ERR>("Failed power state change on a reset button press",
215 entry("ERROR=%s", e.what()));
216 }
217}
Matt Spinler69f93512018-11-26 14:55:58 -0600218
219void Handler::idPressed(sdbusplus::message::message& msg)
220{
221 std::string groupPath{ledGroupBasePath};
222 groupPath += ID_LED_GROUP;
223
224 auto service = getService(groupPath, ledGroupIface);
225
226 if (service.empty())
227 {
228 log<level::INFO>("No identify LED group found during ID button press",
229 entry("GROUP=%s", groupPath.c_str()));
230 return;
231 }
232
233 try
234 {
235 auto method = bus.new_method_call(service.c_str(), groupPath.c_str(),
236 propertyIface, "Get");
237 method.append(ledGroupIface, "Asserted");
238 auto result = bus.call(method);
239
Patrick Williams5ed4cc02020-05-13 17:52:15 -0500240 std::variant<bool> state;
Matt Spinler69f93512018-11-26 14:55:58 -0600241 result.read(state);
242
Patrick Williams51f5e8b2020-05-13 11:33:44 -0500243 state = !std::get<bool>(state);
Matt Spinler69f93512018-11-26 14:55:58 -0600244
Patrick Williams51f5e8b2020-05-13 11:33:44 -0500245 log<level::INFO>("Changing ID LED group state on ID LED press",
246 entry("GROUP=%s", groupPath.c_str()),
247 entry("STATE=%d", std::get<bool>(state)));
Matt Spinler69f93512018-11-26 14:55:58 -0600248
249 method = bus.new_method_call(service.c_str(), groupPath.c_str(),
250 propertyIface, "Set");
251
252 method.append(ledGroupIface, "Asserted", state);
253 result = bus.call(method);
254 }
Patrick Williams6d724ce2021-10-06 12:40:26 -0500255 catch (const sdbusplus::exception::exception& e)
Matt Spinler69f93512018-11-26 14:55:58 -0600256 {
257 log<level::ERR>("Error toggling ID LED group on ID button press",
258 entry("ERROR=%s", e.what()));
259 }
260}
Matt Spinlerfb35a322018-11-26 14:30:30 -0600261} // namespace button
262} // namespace phosphor