xref: /openbmc/phosphor-power/utility.hpp (revision f0f02b9ae21ece3d691c1bbea348b468787ed2ff)
1974c916eSMatt Spinler #pragma once
2974c916eSMatt Spinler 
3882ce956SMatt Spinler #include <phosphor-logging/elog.hpp>
4*f0f02b9aSMatt Spinler #include <phosphor-logging/log.hpp>
5974c916eSMatt Spinler #include <sdbusplus/bus.hpp>
6974c916eSMatt Spinler #include <string>
7974c916eSMatt Spinler 
8974c916eSMatt Spinler namespace witherspoon
9974c916eSMatt Spinler {
10974c916eSMatt Spinler namespace power
11974c916eSMatt Spinler {
12974c916eSMatt Spinler namespace util
13974c916eSMatt Spinler {
14974c916eSMatt Spinler 
15882ce956SMatt Spinler constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
16882ce956SMatt Spinler constexpr auto SYSTEMD_ROOT = "/org/freedesktop/systemd1";
17882ce956SMatt Spinler constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
18882ce956SMatt Spinler constexpr auto POWEROFF_TARGET = "obmc-chassis-hard-poweroff@0.target";
19974c916eSMatt Spinler constexpr auto PROPERTY_INTF = "org.freedesktop.DBus.Properties";
20974c916eSMatt Spinler 
21974c916eSMatt Spinler /**
22974c916eSMatt Spinler  * @brief Get the service name from the mapper for the
23974c916eSMatt Spinler  *        interface and path passed in.
24974c916eSMatt Spinler  *
25974c916eSMatt Spinler  * @param[in] path - the D-Bus path name
26974c916eSMatt Spinler  * @param[in] interface - the D-Bus interface name
27974c916eSMatt Spinler  * @param[in] bus - the D-Bus object
28974c916eSMatt Spinler  *
29974c916eSMatt Spinler  * @return The service name
30974c916eSMatt Spinler  */
31*f0f02b9aSMatt Spinler std::string getService(const std::string& path, const std::string& interface,
32974c916eSMatt Spinler                        sdbusplus::bus::bus& bus);
33974c916eSMatt Spinler 
34974c916eSMatt Spinler /**
35974c916eSMatt Spinler  * @brief Read a D-Bus property
36974c916eSMatt Spinler  *
37974c916eSMatt Spinler  * @param[in] interface - the interface the property is on
38974c916eSMatt Spinler  * @param[in] propertName - the name of the property
39974c916eSMatt Spinler  * @param[in] path - the D-Bus path
40974c916eSMatt Spinler  * @param[in] service - the D-Bus service
41974c916eSMatt Spinler  * @param[in] bus - the D-Bus object
42974c916eSMatt Spinler  * @param[out] value - filled in with the property value
43974c916eSMatt Spinler  */
44974c916eSMatt Spinler template <typename T>
45*f0f02b9aSMatt Spinler void getProperty(const std::string& interface, const std::string& propertyName,
46*f0f02b9aSMatt Spinler                  const std::string& path, const std::string& service,
47*f0f02b9aSMatt Spinler                  sdbusplus::bus::bus& bus, T& value)
48974c916eSMatt Spinler {
49974c916eSMatt Spinler     sdbusplus::message::variant<T> property;
50974c916eSMatt Spinler 
51*f0f02b9aSMatt Spinler     auto method = bus.new_method_call(service.c_str(), path.c_str(),
52*f0f02b9aSMatt Spinler                                       PROPERTY_INTF, "Get");
53974c916eSMatt Spinler 
54974c916eSMatt Spinler     method.append(interface, propertyName);
55974c916eSMatt Spinler 
56974c916eSMatt Spinler     auto reply = bus.call(method);
57974c916eSMatt Spinler     if (reply.is_method_error())
58974c916eSMatt Spinler     {
59974c916eSMatt Spinler         using namespace phosphor::logging;
60974c916eSMatt Spinler         log<level::ERR>("Error in property get call",
61974c916eSMatt Spinler                         entry("PATH=%s", path.c_str()),
62974c916eSMatt Spinler                         entry("PROPERTY=%s", propertyName.c_str()));
63882ce956SMatt Spinler 
64974c916eSMatt Spinler         // TODO openbmc/openbmc#851 - Once available, throw returned error
65974c916eSMatt Spinler         throw std::runtime_error("Error in property get call");
66974c916eSMatt Spinler     }
67974c916eSMatt Spinler 
68974c916eSMatt Spinler     reply.read(property);
69974c916eSMatt Spinler     value = sdbusplus::message::variant_ns::get<T>(property);
70974c916eSMatt Spinler }
71974c916eSMatt Spinler 
7248b4a430SMatt Spinler /**
730a4f519bSBrandon Wyman  * @brief Write a D-Bus property
740a4f519bSBrandon Wyman  *
750a4f519bSBrandon Wyman  * @param[in] interface - the interface the property is on
760a4f519bSBrandon Wyman  * @param[in] propertName - the name of the property
770a4f519bSBrandon Wyman  * @param[in] path - the D-Bus path
780a4f519bSBrandon Wyman  * @param[in] service - the D-Bus service
790a4f519bSBrandon Wyman  * @param[in] bus - the D-Bus object
800a4f519bSBrandon Wyman  * @param[in] value - the value to set the property to
810a4f519bSBrandon Wyman  */
820a4f519bSBrandon Wyman template <typename T>
83*f0f02b9aSMatt Spinler void setProperty(const std::string& interface, const std::string& propertyName,
84*f0f02b9aSMatt Spinler                  const std::string& path, const std::string& service,
85*f0f02b9aSMatt Spinler                  sdbusplus::bus::bus& bus, T& value)
860a4f519bSBrandon Wyman {
870a4f519bSBrandon Wyman     sdbusplus::message::variant<T> propertyValue(value);
880a4f519bSBrandon Wyman 
89*f0f02b9aSMatt Spinler     auto method = bus.new_method_call(service.c_str(), path.c_str(),
90*f0f02b9aSMatt Spinler                                       PROPERTY_INTF, "Set");
910a4f519bSBrandon Wyman 
920a4f519bSBrandon Wyman     method.append(interface, propertyName, propertyValue);
930a4f519bSBrandon Wyman 
940a4f519bSBrandon Wyman     auto reply = bus.call(method);
950a4f519bSBrandon Wyman     if (reply.is_method_error())
960a4f519bSBrandon Wyman     {
970a4f519bSBrandon Wyman         using namespace phosphor::logging;
980a4f519bSBrandon Wyman         log<level::ERR>("Error in property set call",
990a4f519bSBrandon Wyman                         entry("SERVICE=%s", service.c_str()),
1000a4f519bSBrandon Wyman                         entry("PATH=%s", path.c_str()),
1010a4f519bSBrandon Wyman                         entry("PROPERTY=%s", propertyName.c_str()));
1020a4f519bSBrandon Wyman 
1030a4f519bSBrandon Wyman         // TODO openbmc/openbmc#851 - Once available, throw returned error
1040a4f519bSBrandon Wyman         throw std::runtime_error("Error in property set call");
1050a4f519bSBrandon Wyman     }
1060a4f519bSBrandon Wyman }
1070a4f519bSBrandon Wyman 
1080a4f519bSBrandon Wyman /**
109882ce956SMatt Spinler  * Logs an error and powers off the system.
11048b4a430SMatt Spinler  *
111882ce956SMatt Spinler  * @tparam T - error that will be logged before the power off
11248b4a430SMatt Spinler  * @param[in] bus - D-Bus object
11348b4a430SMatt Spinler  */
114882ce956SMatt Spinler template <typename T>
115882ce956SMatt Spinler void powerOff(sdbusplus::bus::bus& bus)
116882ce956SMatt Spinler {
117882ce956SMatt Spinler     phosphor::logging::report<T>();
118882ce956SMatt Spinler 
119*f0f02b9aSMatt Spinler     auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
120*f0f02b9aSMatt Spinler                                       SYSTEMD_INTERFACE, "StartUnit");
121882ce956SMatt Spinler 
122882ce956SMatt Spinler     method.append(POWEROFF_TARGET);
123882ce956SMatt Spinler     method.append("replace");
124882ce956SMatt Spinler 
125882ce956SMatt Spinler     bus.call_noreply(method);
126882ce956SMatt Spinler }
12748b4a430SMatt Spinler 
128*f0f02b9aSMatt Spinler } // namespace util
129*f0f02b9aSMatt Spinler } // namespace power
130*f0f02b9aSMatt Spinler } // namespace witherspoon
131