blob: 32e97256a07302a9a6e3a9c4f490ec7872bb5fd8 [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
Myung Bae7066dc52024-08-20 11:01:57 -0500156inline void handleLedGroupSubtree(
157 const std::string& objPath, const boost::system::error_code& ec,
158 const dbus::utility::MapperGetSubTreeResponse& subtree,
159 const std::function<void(const boost::system::error_code& ec,
160 const std::string& ledGroupPath,
161 const std::string& service)>& callback)
162{
163 if (ec)
164 {
165 // Callback will handle the error
166 callback(ec, "", "");
167 return;
168 }
169
170 if (subtree.empty())
171 {
172 // Callback will handle the error
173 BMCWEB_LOG_DEBUG(
174 "No LED group associated with the specified object path: {}",
175 objPath);
176 callback(ec, "", "");
177 return;
178 }
179
180 if (subtree.size() > 1)
181 {
182 // Callback will handle the error
183 BMCWEB_LOG_DEBUG(
184 "More than one LED group associated with the object {}: {}",
185 objPath, subtree.size());
186 callback(ec, "", "");
187 return;
188 }
189
190 const auto& [ledGroupPath, serviceMap] = *subtree.begin();
191 const auto& [service, interfaces] = *serviceMap.begin();
192 callback(ec, ledGroupPath, service);
193}
194
195inline void getLedGroupPath(
196 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
197 const std::string& objPath,
198 std::function<void(const boost::system::error_code& ec,
199 const std::string& ledGroupPath,
200 const std::string& service)>&& callback)
201{
202 static constexpr const char* ledObjectPath =
203 "/xyz/openbmc_project/led/groups";
204 sdbusplus::message::object_path ledGroupAssociatedPath =
205 objPath + "/identifying";
206
207 dbus::utility::getAssociatedSubTree(
208 ledGroupAssociatedPath, sdbusplus::message::object_path(ledObjectPath),
209 0, ledGroupInterface,
210 [asyncResp, objPath, callback{std::move(callback)}](
211 const boost::system::error_code& ec,
212 const dbus::utility::MapperGetSubTreeResponse& subtree) {
213 handleLedGroupSubtree(objPath, ec, subtree, callback);
214 });
215}
216
217inline void afterGetLedState(
218 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
219 const boost::system::error_code& ec, bool assert)
220{
221 if (ec)
222 {
223 if (ec.value() != EBADR)
224 {
225 BMCWEB_LOG_ERROR("DBUS response error for get ledState {}",
226 ec.value());
227 messages::internalError(asyncResp->res);
228 }
229 return;
230 }
231
232 asyncResp->res.jsonValue["LocationIndicatorActive"] = assert;
233}
234
235inline void getLedState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
236 const boost::system::error_code& ec,
237 const std::string& ledGroupPath,
238 const std::string& service)
239{
240 if (ec)
241 {
242 if (ec.value() != EBADR)
243 {
244 BMCWEB_LOG_ERROR("DBUS response error {}", ec.value());
245 messages::internalError(asyncResp->res);
246 }
247 return;
248 }
249
250 if (ledGroupPath.empty() || service.empty())
251 {
252 // No LED group associated, not an error
253 return;
254 }
255
256 sdbusplus::asio::getProperty<bool>(
257 *crow::connections::systemBus, service, ledGroupPath,
258 "xyz.openbmc_project.Led.Group", "Asserted",
259 std::bind_front(afterGetLedState, asyncResp));
260}
261
262/**
263 * @brief Retrieves identify led group properties over dbus
264 *
265 * @param[in] asyncResp Shared pointer for generating response
266 * message.
267 * @param[in] objPath Object path on PIM
268 *
269 * @return None.
270 */
271inline void getLocationIndicatorActive(
272 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
273 const std::string& objPath)
274{
275 BMCWEB_LOG_DEBUG("Get LocationIndicatorActive for {}", objPath);
276 getLedGroupPath(asyncResp, objPath,
277 [asyncResp](const boost::system::error_code& ec,
278 const std::string& ledGroupPath,
279 const std::string& service) {
280 getLedState(asyncResp, ec, ledGroupPath, service);
281 });
282}
283
284inline void setLedState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
285 bool ledState, const boost::system::error_code& ec,
286 const std::string& ledGroupPath,
287 const std::string& service)
288{
289 if (ec)
290 {
291 if (ec.value() == EBADR)
292 {
293 messages::propertyUnknown(asyncResp->res,
294 "LocationIndicatorActive");
295 return;
296 }
297 BMCWEB_LOG_ERROR("DBUS response error {}", ec.value());
298 messages::internalError(asyncResp->res);
299 return;
300 }
301
302 if (ledGroupPath.empty() || service.empty())
303 {
304 messages::propertyUnknown(asyncResp->res, "LocationIndicatorActive");
305 return;
306 }
307
308 setDbusProperty(asyncResp, "LocationIndicatorActive", service, ledGroupPath,
309 "xyz.openbmc_project.Led.Group", "Asserted", ledState);
310}
311
312/**
313 * @brief Sets identify led group properties
314 *
315 * @param[in] asyncResp Shared pointer for generating response
316 * message.
317 * @param[in] objPath Object path on PIM
318 * @param[in] ledState LED state passed from request
319 *
320 * @return None.
321 */
322inline void setLocationIndicatorActive(
323 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
324 const std::string& objPath, bool ledState)
325{
326 BMCWEB_LOG_DEBUG("Set LocationIndicatorActive for {}", objPath);
327 getLedGroupPath(
328 asyncResp, objPath,
329 [asyncResp, ledState](const boost::system::error_code& ec,
330 const std::string& ledGroupPath,
331 const std::string& service) {
332 setLedState(asyncResp, ledState, ec, ledGroupPath, service);
333 });
334}
335
Ed Tanous23a21a12020-07-25 04:45:05 +0000336} // namespace redfish