blob: e868bf3490ba3a48530e33fde60c1a55dfd2bf37 [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>
Myung Bae7066dc52024-08-20 11:01:57 -050023#include <string_view>
24#include <utility>
John Edward Broadbent7e860f12021-04-08 15:57:16 -070025
James Feist1c8fba92019-12-20 15:12:07 -080026namespace redfish
27{
Myung Bae7066dc52024-08-20 11:01:57 -050028static constexpr std::array<std::string_view, 1> ledGroupInterface = {
29 "xyz.openbmc_project.Led.Group"};
James Feist1c8fba92019-12-20 15:12:07 -080030/**
31 * @brief Retrieves identify led group properties over dbus
32 *
Ed Tanousac106bf2023-06-07 09:24:59 -070033 * @param[in] asyncResp Shared pointer for generating response message.
James Feist1c8fba92019-12-20 15:12:07 -080034 *
35 * @return None.
36 */
Gunnar Mills9f8bfa72020-09-28 13:45:19 -050037// TODO (Gunnar): Remove IndicatorLED after enough time has passed
Patrick Williams504af5a2025-02-03 14:29:03 -050038inline void getIndicatorLedState(
39 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
James Feist1c8fba92019-12-20 15:12:07 -080040{
Ed Tanous62598e32023-07-17 17:06:25 -070041 BMCWEB_LOG_DEBUG("Get led groups");
Ed Tanousdeae6a72024-11-11 21:58:57 -080042 dbus::utility::getProperty<bool>(
43 "xyz.openbmc_project.LED.GroupManager",
Jonathan Doman1e1e5982021-06-11 09:36:17 -070044 "/xyz/openbmc_project/led/groups/enclosure_identify_blink",
45 "xyz.openbmc_project.Led.Group", "Asserted",
Ed Tanousac106bf2023-06-07 09:24:59 -070046 [asyncResp](const boost::system::error_code& ec, const bool blinking) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -040047 // Some systems may not have enclosure_identify_blink object so
48 // proceed to get enclosure_identify state.
49 if (ec == boost::system::errc::invalid_argument)
James Feist1c8fba92019-12-20 15:12:07 -080050 {
Ed Tanous62598e32023-07-17 17:06:25 -070051 BMCWEB_LOG_DEBUG(
Patrick Williamsbd79bce2024-08-16 15:22:20 -040052 "Get identity blinking LED failed, mismatch in property type");
Ed Tanousac106bf2023-06-07 09:24:59 -070053 messages::internalError(asyncResp->res);
Jonathan Doman1e1e5982021-06-11 09:36:17 -070054 return;
James Feist1c8fba92019-12-20 15:12:07 -080055 }
James Feist1c8fba92019-12-20 15:12:07 -080056
Patrick Williamsbd79bce2024-08-16 15:22:20 -040057 // Blinking ON, no need to check enclosure_identify assert.
58 if (!ec && blinking)
Jonathan Doman1e1e5982021-06-11 09:36:17 -070059 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -040060 asyncResp->res.jsonValue["IndicatorLED"] =
61 chassis::IndicatorLED::Blinking;
Jonathan Doman1e1e5982021-06-11 09:36:17 -070062 return;
63 }
64
Ed Tanousdeae6a72024-11-11 21:58:57 -080065 dbus::utility::getProperty<bool>(
Patrick Williamsbd79bce2024-08-16 15:22:20 -040066 "xyz.openbmc_project.LED.GroupManager",
67 "/xyz/openbmc_project/led/groups/enclosure_identify",
68 "xyz.openbmc_project.Led.Group", "Asserted",
69 [asyncResp](const boost::system::error_code& ec2,
70 const bool ledOn) {
71 if (ec2 == boost::system::errc::invalid_argument)
72 {
73 BMCWEB_LOG_DEBUG(
74 "Get enclosure identity led failed, mismatch in property type");
75 messages::internalError(asyncResp->res);
76 return;
77 }
78
79 if (ec2)
80 {
81 return;
82 }
83
84 if (ledOn)
85 {
86 asyncResp->res.jsonValue["IndicatorLED"] =
87 chassis::IndicatorLED::Lit;
88 }
89 else
90 {
91 asyncResp->res.jsonValue["IndicatorLED"] =
92 chassis::IndicatorLED::Off;
93 }
94 });
Jonathan Doman1e1e5982021-06-11 09:36:17 -070095 });
James Feist1c8fba92019-12-20 15:12:07 -080096}
97
98/**
99 * @brief Sets identify led group properties
100 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700101 * @param[in] asyncResp Shared pointer for generating response message.
James Feist1c8fba92019-12-20 15:12:07 -0800102 * @param[in] ledState LED state passed from request
103 *
104 * @return None.
105 */
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500106// TODO (Gunnar): Remove IndicatorLED after enough time has passed
Patrick Williams504af5a2025-02-03 14:29:03 -0500107inline void setIndicatorLedState(
108 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
109 const std::string& ledState)
James Feist1c8fba92019-12-20 15:12:07 -0800110{
Ed Tanous62598e32023-07-17 17:06:25 -0700111 BMCWEB_LOG_DEBUG("Set led groups");
James Feist1c8fba92019-12-20 15:12:07 -0800112 bool ledOn = false;
113 bool ledBlinkng = false;
114
115 if (ledState == "Lit")
116 {
117 ledOn = true;
118 }
119 else if (ledState == "Blinking")
120 {
121 ledBlinkng = true;
122 }
123 else if (ledState != "Off")
124 {
Ed Tanousac106bf2023-06-07 09:24:59 -0700125 messages::propertyValueNotInList(asyncResp->res, ledState,
126 "IndicatorLED");
James Feist1c8fba92019-12-20 15:12:07 -0800127 return;
128 }
129
George Liu9ae226f2023-06-21 17:56:46 +0800130 sdbusplus::asio::setProperty(
131 *crow::connections::systemBus, "xyz.openbmc_project.LED.GroupManager",
132 "/xyz/openbmc_project/led/groups/enclosure_identify_blink",
133 "xyz.openbmc_project.Led.Group", "Asserted", ledBlinkng,
Ed Tanousac106bf2023-06-07 09:24:59 -0700134 [asyncResp, ledOn,
Ed Tanous5e7e2dc2023-02-16 10:37:01 -0800135 ledBlinkng](const boost::system::error_code& ec) mutable {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400136 if (ec)
James Feist1c8fba92019-12-20 15:12:07 -0800137 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400138 // Some systems may not have enclosure_identify_blink object so
139 // Lets set enclosure_identify state to true if Blinking is
140 // true.
141 if (ledBlinkng)
142 {
143 ledOn = true;
144 }
James Feist1c8fba92019-12-20 15:12:07 -0800145 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400146 setDbusProperty(
147 asyncResp, "IndicatorLED",
148 "xyz.openbmc_project.LED.GroupManager",
149 sdbusplus::message::object_path(
150 "/xyz/openbmc_project/led/groups/enclosure_identify"),
151 "xyz.openbmc_project.Led.Group", "Asserted", ledBlinkng);
152 });
James Feist1c8fba92019-12-20 15:12:07 -0800153}
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500154
155/**
George Liu59a17e42022-10-08 09:27:47 +0800156 * @brief Retrieves identify system led group properties over dbus
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500157 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700158 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500159 *
160 * @return None.
161 */
George Liu59a17e42022-10-08 09:27:47 +0800162inline void getSystemLocationIndicatorActive(
Ed Tanousac106bf2023-06-07 09:24:59 -0700163 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500164{
Ed Tanous62598e32023-07-17 17:06:25 -0700165 BMCWEB_LOG_DEBUG("Get LocationIndicatorActive");
Ed Tanousdeae6a72024-11-11 21:58:57 -0800166 dbus::utility::getProperty<bool>(
167 "xyz.openbmc_project.LED.GroupManager",
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700168 "/xyz/openbmc_project/led/groups/enclosure_identify_blink",
169 "xyz.openbmc_project.Led.Group", "Asserted",
Ed Tanousac106bf2023-06-07 09:24:59 -0700170 [asyncResp](const boost::system::error_code& ec, const bool blinking) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400171 // Some systems may not have enclosure_identify_blink object so
172 // proceed to get enclosure_identify state.
173 if (ec == boost::system::errc::invalid_argument)
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500174 {
Ed Tanous62598e32023-07-17 17:06:25 -0700175 BMCWEB_LOG_DEBUG(
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400176 "Get identity blinking LED failed, mismatch in property type");
Ed Tanousac106bf2023-06-07 09:24:59 -0700177 messages::internalError(asyncResp->res);
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700178 return;
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500179 }
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500180
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400181 // Blinking ON, no need to check enclosure_identify assert.
182 if (!ec && blinking)
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700183 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400184 asyncResp->res.jsonValue["LocationIndicatorActive"] = true;
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700185 return;
186 }
187
Ed Tanousdeae6a72024-11-11 21:58:57 -0800188 dbus::utility::getProperty<bool>(
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400189 "xyz.openbmc_project.LED.GroupManager",
190 "/xyz/openbmc_project/led/groups/enclosure_identify",
191 "xyz.openbmc_project.Led.Group", "Asserted",
192 [asyncResp](const boost::system::error_code& ec2,
193 const bool ledOn) {
194 if (ec2 == boost::system::errc::invalid_argument)
195 {
196 BMCWEB_LOG_DEBUG(
197 "Get enclosure identity led failed, mismatch in property type");
198 messages::internalError(asyncResp->res);
199 return;
200 }
201
202 if (ec2)
203 {
204 return;
205 }
206
207 asyncResp->res.jsonValue["LocationIndicatorActive"] = ledOn;
208 });
Jonathan Doman1e1e5982021-06-11 09:36:17 -0700209 });
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500210}
211
212/**
George Liu59a17e42022-10-08 09:27:47 +0800213 * @brief Sets identify system led group properties
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500214 *
Ed Tanousac106bf2023-06-07 09:24:59 -0700215 * @param[in] asyncResp Shared pointer for generating response message.
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500216 * @param[in] ledState LED state passed from request
217 *
218 * @return None.
219 */
George Liu59a17e42022-10-08 09:27:47 +0800220inline void setSystemLocationIndicatorActive(
Ed Tanousac106bf2023-06-07 09:24:59 -0700221 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const bool ledState)
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500222{
Ed Tanous62598e32023-07-17 17:06:25 -0700223 BMCWEB_LOG_DEBUG("Set LocationIndicatorActive");
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500224
George Liu9ae226f2023-06-21 17:56:46 +0800225 sdbusplus::asio::setProperty(
226 *crow::connections::systemBus, "xyz.openbmc_project.LED.GroupManager",
227 "/xyz/openbmc_project/led/groups/enclosure_identify_blink",
228 "xyz.openbmc_project.Led.Group", "Asserted", ledState,
229 [asyncResp, ledState](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400230 if (ec)
231 {
232 // Some systems may not have enclosure_identify_blink object so
233 // lets set enclosure_identify state also if
234 // enclosure_identify_blink failed
235 setDbusProperty(
236 asyncResp, "LocationIndicatorActive",
237 "xyz.openbmc_project.LED.GroupManager",
238 sdbusplus::message::object_path(
239 "/xyz/openbmc_project/led/groups/enclosure_identify"),
240 "xyz.openbmc_project.Led.Group", "Asserted", ledState);
241 }
242 });
Gunnar Mills9f8bfa72020-09-28 13:45:19 -0500243}
Myung Bae7066dc52024-08-20 11:01:57 -0500244
245inline void handleLedGroupSubtree(
246 const std::string& objPath, const boost::system::error_code& ec,
247 const dbus::utility::MapperGetSubTreeResponse& subtree,
248 const std::function<void(const boost::system::error_code& ec,
249 const std::string& ledGroupPath,
250 const std::string& service)>& callback)
251{
252 if (ec)
253 {
254 // Callback will handle the error
255 callback(ec, "", "");
256 return;
257 }
258
259 if (subtree.empty())
260 {
261 // Callback will handle the error
262 BMCWEB_LOG_DEBUG(
263 "No LED group associated with the specified object path: {}",
264 objPath);
265 callback(ec, "", "");
266 return;
267 }
268
269 if (subtree.size() > 1)
270 {
271 // Callback will handle the error
272 BMCWEB_LOG_DEBUG(
273 "More than one LED group associated with the object {}: {}",
274 objPath, subtree.size());
275 callback(ec, "", "");
276 return;
277 }
278
279 const auto& [ledGroupPath, serviceMap] = *subtree.begin();
280 const auto& [service, interfaces] = *serviceMap.begin();
281 callback(ec, ledGroupPath, service);
282}
283
284inline void getLedGroupPath(
285 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
286 const std::string& objPath,
287 std::function<void(const boost::system::error_code& ec,
288 const std::string& ledGroupPath,
289 const std::string& service)>&& callback)
290{
291 static constexpr const char* ledObjectPath =
292 "/xyz/openbmc_project/led/groups";
293 sdbusplus::message::object_path ledGroupAssociatedPath =
294 objPath + "/identifying";
295
296 dbus::utility::getAssociatedSubTree(
297 ledGroupAssociatedPath, sdbusplus::message::object_path(ledObjectPath),
298 0, ledGroupInterface,
299 [asyncResp, objPath, callback{std::move(callback)}](
300 const boost::system::error_code& ec,
301 const dbus::utility::MapperGetSubTreeResponse& subtree) {
302 handleLedGroupSubtree(objPath, ec, subtree, callback);
303 });
304}
305
306inline void afterGetLedState(
307 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
308 const boost::system::error_code& ec, bool assert)
309{
310 if (ec)
311 {
312 if (ec.value() != EBADR)
313 {
314 BMCWEB_LOG_ERROR("DBUS response error for get ledState {}",
315 ec.value());
316 messages::internalError(asyncResp->res);
317 }
318 return;
319 }
320
321 asyncResp->res.jsonValue["LocationIndicatorActive"] = assert;
322}
323
324inline void getLedState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
325 const boost::system::error_code& ec,
326 const std::string& ledGroupPath,
327 const std::string& service)
328{
329 if (ec)
330 {
331 if (ec.value() != EBADR)
332 {
333 BMCWEB_LOG_ERROR("DBUS response error {}", ec.value());
334 messages::internalError(asyncResp->res);
335 }
336 return;
337 }
338
339 if (ledGroupPath.empty() || service.empty())
340 {
341 // No LED group associated, not an error
342 return;
343 }
344
345 sdbusplus::asio::getProperty<bool>(
346 *crow::connections::systemBus, service, ledGroupPath,
347 "xyz.openbmc_project.Led.Group", "Asserted",
348 std::bind_front(afterGetLedState, asyncResp));
349}
350
351/**
352 * @brief Retrieves identify led group properties over dbus
353 *
354 * @param[in] asyncResp Shared pointer for generating response
355 * message.
356 * @param[in] objPath Object path on PIM
357 *
358 * @return None.
359 */
360inline void getLocationIndicatorActive(
361 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
362 const std::string& objPath)
363{
364 BMCWEB_LOG_DEBUG("Get LocationIndicatorActive for {}", objPath);
365 getLedGroupPath(asyncResp, objPath,
366 [asyncResp](const boost::system::error_code& ec,
367 const std::string& ledGroupPath,
368 const std::string& service) {
369 getLedState(asyncResp, ec, ledGroupPath, service);
370 });
371}
372
373inline void setLedState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
374 bool ledState, const boost::system::error_code& ec,
375 const std::string& ledGroupPath,
376 const std::string& service)
377{
378 if (ec)
379 {
380 if (ec.value() == EBADR)
381 {
382 messages::propertyUnknown(asyncResp->res,
383 "LocationIndicatorActive");
384 return;
385 }
386 BMCWEB_LOG_ERROR("DBUS response error {}", ec.value());
387 messages::internalError(asyncResp->res);
388 return;
389 }
390
391 if (ledGroupPath.empty() || service.empty())
392 {
393 messages::propertyUnknown(asyncResp->res, "LocationIndicatorActive");
394 return;
395 }
396
397 setDbusProperty(asyncResp, "LocationIndicatorActive", service, ledGroupPath,
398 "xyz.openbmc_project.Led.Group", "Asserted", ledState);
399}
400
401/**
402 * @brief Sets identify led group properties
403 *
404 * @param[in] asyncResp Shared pointer for generating response
405 * message.
406 * @param[in] objPath Object path on PIM
407 * @param[in] ledState LED state passed from request
408 *
409 * @return None.
410 */
411inline void setLocationIndicatorActive(
412 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
413 const std::string& objPath, bool ledState)
414{
415 BMCWEB_LOG_DEBUG("Set LocationIndicatorActive for {}", objPath);
416 getLedGroupPath(
417 asyncResp, objPath,
418 [asyncResp, ledState](const boost::system::error_code& ec,
419 const std::string& ledGroupPath,
420 const std::string& service) {
421 setLedState(asyncResp, ledState, ec, ledGroupPath, service);
422 });
423}
424
Ed Tanous23a21a12020-07-25 04:45:05 +0000425} // namespace redfish