blob: b74dc4d5a0b77e9bc45256055b0593145c87b085 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
3// SPDX-FileCopyrightText: Copyright 2019 Intel Corporation
James Feist1c8fba92019-12-20 15:12:07 -08004#pragma once
5
6#include "async_resp.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -08007#include "dbus_singleton.hpp"
James Feist1c8fba92019-12-20 15:12:07 -08008#include "dbus_utility.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -08009#include "error_messages.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -070010#include "generated/enums/chassis.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080011#include "logging.hpp"
12#include "utils/dbus_utils.hpp"
James Feist1c8fba92019-12-20 15:12:07 -080013
Myung Bae7066dc52024-08-20 11:01:57 -050014#include <asm-generic/errno.h>
15
16#include <boost/system/error_code.hpp>
Jonathan Doman1e1e5982021-06-11 09:36:17 -070017#include <sdbusplus/asio/property.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080018#include <sdbusplus/message/native_types.hpp>
19
Myung Bae7066dc52024-08-20 11:01:57 -050020#include <array>
21#include <functional>
Ed Tanousd7857202025-01-28 15:32:26 -080022#include <memory>
Ed Tanous177612a2025-02-14 15:16:09 -080023#include <string>
Myung Bae7066dc52024-08-20 11:01:57 -050024#include <string_view>
25#include <utility>
John Edward Broadbent7e860f12021-04-08 15:57:16 -070026
James Feist1c8fba92019-12-20 15:12:07 -080027namespace redfish
28{
Myung Bae7066dc52024-08-20 11:01:57 -050029static constexpr std::array<std::string_view, 1> ledGroupInterface = {
30 "xyz.openbmc_project.Led.Group"};
James Feist1c8fba92019-12-20 15:12:07 -080031/**
32 * @brief Retrieves identify led group properties over dbus
33 *
Ed Tanousac106bf2023-06-07 09:24:59 -070034 * @param[in] asyncResp Shared pointer for generating response message.
James Feist1c8fba92019-12-20 15:12:07 -080035 *
36 * @return None.
37 */
Gunnar Mills9f8bfa72020-09-28 13:45:19 -050038// TODO (Gunnar): Remove IndicatorLED after enough time has passed
Patrick Williams504af5a2025-02-03 14:29:03 -050039inline void getIndicatorLedState(
40 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
James Feist1c8fba92019-12-20 15:12:07 -080041{
Ed Tanous62598e32023-07-17 17:06:25 -070042 BMCWEB_LOG_DEBUG("Get led groups");
Ed Tanousdeae6a72024-11-11 21:58:57 -080043 dbus::utility::getProperty<bool>(
44 "xyz.openbmc_project.LED.GroupManager",
Jonathan Doman1e1e5982021-06-11 09:36:17 -070045 "/xyz/openbmc_project/led/groups/enclosure_identify_blink",
46 "xyz.openbmc_project.Led.Group", "Asserted",
Ed Tanousac106bf2023-06-07 09:24:59 -070047 [asyncResp](const boost::system::error_code& ec, const bool blinking) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -040048 // Some systems may not have enclosure_identify_blink object so
49 // proceed to get enclosure_identify state.
50 if (ec == boost::system::errc::invalid_argument)
James Feist1c8fba92019-12-20 15:12:07 -080051 {
Ed Tanous62598e32023-07-17 17:06:25 -070052 BMCWEB_LOG_DEBUG(
Patrick Williamsbd79bce2024-08-16 15:22:20 -040053 "Get identity blinking LED failed, mismatch in property type");
Ed Tanousac106bf2023-06-07 09:24:59 -070054 messages::internalError(asyncResp->res);
Jonathan Doman1e1e5982021-06-11 09:36:17 -070055 return;
James Feist1c8fba92019-12-20 15:12:07 -080056 }
James Feist1c8fba92019-12-20 15:12:07 -080057
Patrick Williamsbd79bce2024-08-16 15:22:20 -040058 // Blinking ON, no need to check enclosure_identify assert.
59 if (!ec && blinking)
Jonathan Doman1e1e5982021-06-11 09:36:17 -070060 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -040061 asyncResp->res.jsonValue["IndicatorLED"] =
62 chassis::IndicatorLED::Blinking;
Jonathan Doman1e1e5982021-06-11 09:36:17 -070063 return;
64 }
65
Ed Tanousdeae6a72024-11-11 21:58:57 -080066 dbus::utility::getProperty<bool>(
Patrick Williamsbd79bce2024-08-16 15:22:20 -040067 "xyz.openbmc_project.LED.GroupManager",
68 "/xyz/openbmc_project/led/groups/enclosure_identify",
69 "xyz.openbmc_project.Led.Group", "Asserted",
70 [asyncResp](const boost::system::error_code& ec2,
71 const bool ledOn) {
72 if (ec2 == boost::system::errc::invalid_argument)
73 {
74 BMCWEB_LOG_DEBUG(
75 "Get enclosure identity led failed, mismatch in property type");
76 messages::internalError(asyncResp->res);
77 return;
78 }
79
80 if (ec2)
81 {
82 return;
83 }
84
85 if (ledOn)
86 {
87 asyncResp->res.jsonValue["IndicatorLED"] =
88 chassis::IndicatorLED::Lit;
89 }
90 else
91 {
92 asyncResp->res.jsonValue["IndicatorLED"] =
93 chassis::IndicatorLED::Off;
94 }
95 });
Jonathan Doman1e1e5982021-06-11 09:36:17 -070096 });
James Feist1c8fba92019-12-20 15:12:07 -080097}
98
99/**
100 * @brief Sets identify led group properties
101 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700102 * @param[in] asyncResp Shared pointer for generating response message.
James Feist1c8fba92019-12-20 15:12:07 -0800103 * @param[in] ledState LED state passed from request
104 *
105 * @return None.
106 */
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500107// TODO (Gunnar): Remove IndicatorLED after enough time has passed
Patrick Williams504af5a2025-02-03 14:29:03 -0500108inline void setIndicatorLedState(
109 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
110 const std::string& ledState)
James Feist1c8fba92019-12-20 15:12:07 -0800111{
Ed Tanous62598e32023-07-17 17:06:25 -0700112 BMCWEB_LOG_DEBUG("Set led groups");
James Feist1c8fba92019-12-20 15:12:07 -0800113 bool ledOn = false;
114 bool ledBlinkng = false;
115
116 if (ledState == "Lit")
117 {
118 ledOn = true;
119 }
120 else if (ledState == "Blinking")
121 {
122 ledBlinkng = true;
123 }
124 else if (ledState != "Off")
125 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700126 messages::propertyValueNotInList(asyncResp->res, ledState,
127 "IndicatorLED");
James Feist1c8fba92019-12-20 15:12:07 -0800128 return;
129 }
130
George Liu9ae226f2023-06-21 17:56:46 +0800131 sdbusplus::asio::setProperty(
132 *crow::connections::systemBus, "xyz.openbmc_project.LED.GroupManager",
133 "/xyz/openbmc_project/led/groups/enclosure_identify_blink",
134 "xyz.openbmc_project.Led.Group", "Asserted", ledBlinkng,
Ed Tanousac106bf2023-06-07 09:24:59 -0700135 [asyncResp, ledOn,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800136 ledBlinkng](const boost::system::error_code& ec) mutable {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400137 if (ec)
James Feist1c8fba92019-12-20 15:12:07 -0800138 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400139 // Some systems may not have enclosure_identify_blink object so
140 // Lets set enclosure_identify state to true if Blinking is
141 // true.
142 if (ledBlinkng)
143 {
144 ledOn = true;
145 }
James Feist1c8fba92019-12-20 15:12:07 -0800146 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400147 setDbusProperty(
148 asyncResp, "IndicatorLED",
149 "xyz.openbmc_project.LED.GroupManager",
150 sdbusplus::message::object_path(
151 "/xyz/openbmc_project/led/groups/enclosure_identify"),
152 "xyz.openbmc_project.Led.Group", "Asserted", ledBlinkng);
153 });
James Feist1c8fba92019-12-20 15:12:07 -0800154}
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500155
156/**
George Liu59a17e42022-10-08 09:27:47 +0800157 * @brief Retrieves identify system led group properties over dbus
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500158 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700159 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500160 *
161 * @return None.
162 */
George Liu59a17e42022-10-08 09:27:47 +0800163inline void getSystemLocationIndicatorActive(
Ed Tanousac106bf2023-06-07 09:24:59 -0700164 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500165{
Ed Tanous62598e32023-07-17 17:06:25 -0700166 BMCWEB_LOG_DEBUG("Get LocationIndicatorActive");
Ed Tanousdeae6a72024-11-11 21:58:57 -0800167 dbus::utility::getProperty<bool>(
168 "xyz.openbmc_project.LED.GroupManager",
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700169 "/xyz/openbmc_project/led/groups/enclosure_identify_blink",
170 "xyz.openbmc_project.Led.Group", "Asserted",
Ed Tanousac106bf2023-06-07 09:24:59 -0700171 [asyncResp](const boost::system::error_code& ec, const bool blinking) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400172 // Some systems may not have enclosure_identify_blink object so
173 // proceed to get enclosure_identify state.
174 if (ec == boost::system::errc::invalid_argument)
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500175 {
Ed Tanous62598e32023-07-17 17:06:25 -0700176 BMCWEB_LOG_DEBUG(
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400177 "Get identity blinking LED failed, mismatch in property type");
Ed Tanousac106bf2023-06-07 09:24:59 -0700178 messages::internalError(asyncResp->res);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700179 return;
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500180 }
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500181
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400182 // Blinking ON, no need to check enclosure_identify assert.
183 if (!ec && blinking)
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700184 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400185 asyncResp->res.jsonValue["LocationIndicatorActive"] = true;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700186 return;
187 }
188
Ed Tanousdeae6a72024-11-11 21:58:57 -0800189 dbus::utility::getProperty<bool>(
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400190 "xyz.openbmc_project.LED.GroupManager",
191 "/xyz/openbmc_project/led/groups/enclosure_identify",
192 "xyz.openbmc_project.Led.Group", "Asserted",
193 [asyncResp](const boost::system::error_code& ec2,
194 const bool ledOn) {
195 if (ec2 == boost::system::errc::invalid_argument)
196 {
197 BMCWEB_LOG_DEBUG(
198 "Get enclosure identity led failed, mismatch in property type");
199 messages::internalError(asyncResp->res);
200 return;
201 }
202
203 if (ec2)
204 {
205 return;
206 }
207
208 asyncResp->res.jsonValue["LocationIndicatorActive"] = ledOn;
209 });
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700210 });
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500211}
212
213/**
George Liu59a17e42022-10-08 09:27:47 +0800214 * @brief Sets identify system led group properties
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500215 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700216 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500217 * @param[in] ledState LED state passed from request
218 *
219 * @return None.
220 */
George Liu59a17e42022-10-08 09:27:47 +0800221inline void setSystemLocationIndicatorActive(
Ed Tanousac106bf2023-06-07 09:24:59 -0700222 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const bool ledState)
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500223{
Ed Tanous62598e32023-07-17 17:06:25 -0700224 BMCWEB_LOG_DEBUG("Set LocationIndicatorActive");
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500225
George Liu9ae226f2023-06-21 17:56:46 +0800226 sdbusplus::asio::setProperty(
227 *crow::connections::systemBus, "xyz.openbmc_project.LED.GroupManager",
228 "/xyz/openbmc_project/led/groups/enclosure_identify_blink",
229 "xyz.openbmc_project.Led.Group", "Asserted", ledState,
230 [asyncResp, ledState](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400231 if (ec)
232 {
233 // Some systems may not have enclosure_identify_blink object so
234 // lets set enclosure_identify state also if
235 // enclosure_identify_blink failed
236 setDbusProperty(
237 asyncResp, "LocationIndicatorActive",
238 "xyz.openbmc_project.LED.GroupManager",
239 sdbusplus::message::object_path(
240 "/xyz/openbmc_project/led/groups/enclosure_identify"),
241 "xyz.openbmc_project.Led.Group", "Asserted", ledState);
242 }
243 });
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500244}
Myung Bae7066dc52024-08-20 11:01:57 -0500245
246inline void handleLedGroupSubtree(
247 const std::string& objPath, const boost::system::error_code& ec,
248 const dbus::utility::MapperGetSubTreeResponse& subtree,
249 const std::function<void(const boost::system::error_code& ec,
250 const std::string& ledGroupPath,
251 const std::string& service)>& callback)
252{
253 if (ec)
254 {
255 // Callback will handle the error
256 callback(ec, "", "");
257 return;
258 }
259
260 if (subtree.empty())
261 {
262 // Callback will handle the error
263 BMCWEB_LOG_DEBUG(
264 "No LED group associated with the specified object path: {}",
265 objPath);
266 callback(ec, "", "");
267 return;
268 }
269
270 if (subtree.size() > 1)
271 {
272 // Callback will handle the error
273 BMCWEB_LOG_DEBUG(
274 "More than one LED group associated with the object {}: {}",
275 objPath, subtree.size());
276 callback(ec, "", "");
277 return;
278 }
279
280 const auto& [ledGroupPath, serviceMap] = *subtree.begin();
281 const auto& [service, interfaces] = *serviceMap.begin();
282 callback(ec, ledGroupPath, service);
283}
284
285inline void getLedGroupPath(
286 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
287 const std::string& objPath,
288 std::function<void(const boost::system::error_code& ec,
289 const std::string& ledGroupPath,
290 const std::string& service)>&& callback)
291{
292 static constexpr const char* ledObjectPath =
293 "/xyz/openbmc_project/led/groups";
294 sdbusplus::message::object_path ledGroupAssociatedPath =
295 objPath + "/identifying";
296
297 dbus::utility::getAssociatedSubTree(
298 ledGroupAssociatedPath, sdbusplus::message::object_path(ledObjectPath),
299 0, ledGroupInterface,
300 [asyncResp, objPath, callback{std::move(callback)}](
301 const boost::system::error_code& ec,
302 const dbus::utility::MapperGetSubTreeResponse& subtree) {
303 handleLedGroupSubtree(objPath, ec, subtree, callback);
304 });
305}
306
307inline void afterGetLedState(
308 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
309 const boost::system::error_code& ec, bool assert)
310{
311 if (ec)
312 {
313 if (ec.value() != EBADR)
314 {
315 BMCWEB_LOG_ERROR("DBUS response error for get ledState {}",
316 ec.value());
317 messages::internalError(asyncResp->res);
318 }
319 return;
320 }
321
322 asyncResp->res.jsonValue["LocationIndicatorActive"] = assert;
323}
324
325inline void getLedState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
326 const boost::system::error_code& ec,
327 const std::string& ledGroupPath,
328 const std::string& service)
329{
330 if (ec)
331 {
332 if (ec.value() != EBADR)
333 {
334 BMCWEB_LOG_ERROR("DBUS response error {}", ec.value());
335 messages::internalError(asyncResp->res);
336 }
337 return;
338 }
339
340 if (ledGroupPath.empty() || service.empty())
341 {
342 // No LED group associated, not an error
343 return;
344 }
345
346 sdbusplus::asio::getProperty<bool>(
347 *crow::connections::systemBus, service, ledGroupPath,
348 "xyz.openbmc_project.Led.Group", "Asserted",
349 std::bind_front(afterGetLedState, asyncResp));
350}
351
352/**
353 * @brief Retrieves identify led group properties over dbus
354 *
355 * @param[in] asyncResp Shared pointer for generating response
356 * message.
357 * @param[in] objPath Object path on PIM
358 *
359 * @return None.
360 */
361inline void getLocationIndicatorActive(
362 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
363 const std::string& objPath)
364{
365 BMCWEB_LOG_DEBUG("Get LocationIndicatorActive for {}", objPath);
366 getLedGroupPath(asyncResp, objPath,
367 [asyncResp](const boost::system::error_code& ec,
368 const std::string& ledGroupPath,
369 const std::string& service) {
370 getLedState(asyncResp, ec, ledGroupPath, service);
371 });
372}
373
374inline void setLedState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
375 bool ledState, const boost::system::error_code& ec,
376 const std::string& ledGroupPath,
377 const std::string& service)
378{
379 if (ec)
380 {
381 if (ec.value() == EBADR)
382 {
383 messages::propertyUnknown(asyncResp->res,
384 "LocationIndicatorActive");
385 return;
386 }
387 BMCWEB_LOG_ERROR("DBUS response error {}", ec.value());
388 messages::internalError(asyncResp->res);
389 return;
390 }
391
392 if (ledGroupPath.empty() || service.empty())
393 {
394 messages::propertyUnknown(asyncResp->res, "LocationIndicatorActive");
395 return;
396 }
397
398 setDbusProperty(asyncResp, "LocationIndicatorActive", service, ledGroupPath,
399 "xyz.openbmc_project.Led.Group", "Asserted", ledState);
400}
401
402/**
403 * @brief Sets identify led group properties
404 *
405 * @param[in] asyncResp Shared pointer for generating response
406 * message.
407 * @param[in] objPath Object path on PIM
408 * @param[in] ledState LED state passed from request
409 *
410 * @return None.
411 */
412inline void setLocationIndicatorActive(
413 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
414 const std::string& objPath, bool ledState)
415{
416 BMCWEB_LOG_DEBUG("Set LocationIndicatorActive for {}", objPath);
417 getLedGroupPath(
418 asyncResp, objPath,
419 [asyncResp, ledState](const boost::system::error_code& ec,
420 const std::string& ledGroupPath,
421 const std::string& service) {
422 setLedState(asyncResp, ledState, ec, ledGroupPath, service);
423 });
424}
425
Ed Tanous23a21a12020-07-25 04:45:05 +0000426} // namespace redfish