blob: ac7ef1f82e0d7db9b99c894ccb18b2b7fe52e8c2 [file] [log] [blame]
Matt Spinler974c9162017-08-04 08:36:37 -05001#pragma once
2
Matt Spinler882ce952017-10-05 16:12:41 -05003#include <phosphor-logging/elog.hpp>
Matt Spinlerf0f02b92018-10-25 16:12:43 -05004#include <phosphor-logging/log.hpp>
Matt Spinler974c9162017-08-04 08:36:37 -05005#include <sdbusplus/bus.hpp>
6#include <string>
7
8namespace witherspoon
9{
10namespace power
11{
12namespace util
13{
14
Matt Spinlerf0f02b92018-10-25 16:12:43 -050015constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
16constexpr auto SYSTEMD_ROOT = "/org/freedesktop/systemd1";
Matt Spinler882ce952017-10-05 16:12:41 -050017constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
Matt Spinlerf0f02b92018-10-25 16:12:43 -050018constexpr auto POWEROFF_TARGET = "obmc-chassis-hard-poweroff@0.target";
Matt Spinler974c9162017-08-04 08:36:37 -050019constexpr auto PROPERTY_INTF = "org.freedesktop.DBus.Properties";
20
21/**
22 * @brief Get the service name from the mapper for the
23 * interface and path passed in.
24 *
25 * @param[in] path - the D-Bus path name
26 * @param[in] interface - the D-Bus interface name
27 * @param[in] bus - the D-Bus object
28 *
29 * @return The service name
30 */
Matt Spinlerf0f02b92018-10-25 16:12:43 -050031std::string getService(const std::string& path, const std::string& interface,
Matt Spinler974c9162017-08-04 08:36:37 -050032 sdbusplus::bus::bus& bus);
33
34/**
35 * @brief Read a D-Bus property
36 *
37 * @param[in] interface - the interface the property is on
38 * @param[in] propertName - the name of the property
39 * @param[in] path - the D-Bus path
40 * @param[in] service - the D-Bus service
41 * @param[in] bus - the D-Bus object
42 * @param[out] value - filled in with the property value
43 */
Matt Spinlerf0f02b92018-10-25 16:12:43 -050044template <typename T>
45void getProperty(const std::string& interface, const std::string& propertyName,
46 const std::string& path, const std::string& service,
47 sdbusplus::bus::bus& bus, T& value)
Matt Spinler974c9162017-08-04 08:36:37 -050048{
49 sdbusplus::message::variant<T> property;
50
Matt Spinlerf0f02b92018-10-25 16:12:43 -050051 auto method = bus.new_method_call(service.c_str(), path.c_str(),
52 PROPERTY_INTF, "Get");
Matt Spinler974c9162017-08-04 08:36:37 -050053
54 method.append(interface, propertyName);
55
56 auto reply = bus.call(method);
57 if (reply.is_method_error())
58 {
59 using namespace phosphor::logging;
60 log<level::ERR>("Error in property get call",
Matt Spinler882ce952017-10-05 16:12:41 -050061 entry("PATH=%s", path.c_str()),
62 entry("PROPERTY=%s", propertyName.c_str()));
63
Matt Spinler974c9162017-08-04 08:36:37 -050064 // TODO openbmc/openbmc#851 - Once available, throw returned error
65 throw std::runtime_error("Error in property get call");
66 }
67
68 reply.read(property);
69 value = sdbusplus::message::variant_ns::get<T>(property);
70}
71
Matt Spinler48b4a432017-08-04 11:57:37 -050072/**
Brandon Wyman0a4f5192017-12-06 20:19:08 -060073 * @brief Write a D-Bus property
74 *
75 * @param[in] interface - the interface the property is on
76 * @param[in] propertName - the name of the property
77 * @param[in] path - the D-Bus path
78 * @param[in] service - the D-Bus service
79 * @param[in] bus - the D-Bus object
80 * @param[in] value - the value to set the property to
81 */
Matt Spinlerf0f02b92018-10-25 16:12:43 -050082template <typename T>
83void setProperty(const std::string& interface, const std::string& propertyName,
84 const std::string& path, const std::string& service,
85 sdbusplus::bus::bus& bus, T& value)
Brandon Wyman0a4f5192017-12-06 20:19:08 -060086{
87 sdbusplus::message::variant<T> propertyValue(value);
88
Matt Spinlerf0f02b92018-10-25 16:12:43 -050089 auto method = bus.new_method_call(service.c_str(), path.c_str(),
90 PROPERTY_INTF, "Set");
Brandon Wyman0a4f5192017-12-06 20:19:08 -060091
92 method.append(interface, propertyName, propertyValue);
93
94 auto reply = bus.call(method);
95 if (reply.is_method_error())
96 {
97 using namespace phosphor::logging;
98 log<level::ERR>("Error in property set call",
99 entry("SERVICE=%s", service.c_str()),
100 entry("PATH=%s", path.c_str()),
101 entry("PROPERTY=%s", propertyName.c_str()));
102
103 // TODO openbmc/openbmc#851 - Once available, throw returned error
104 throw std::runtime_error("Error in property set call");
105 }
Brandon Wyman0a4f5192017-12-06 20:19:08 -0600106}
107
108/**
Matt Spinler882ce952017-10-05 16:12:41 -0500109 * Logs an error and powers off the system.
Matt Spinler48b4a432017-08-04 11:57:37 -0500110 *
Matt Spinler882ce952017-10-05 16:12:41 -0500111 * @tparam T - error that will be logged before the power off
Matt Spinler48b4a432017-08-04 11:57:37 -0500112 * @param[in] bus - D-Bus object
113 */
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500114template <typename T>
Matt Spinler882ce952017-10-05 16:12:41 -0500115void powerOff(sdbusplus::bus::bus& bus)
116{
117 phosphor::logging::report<T>();
118
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500119 auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
120 SYSTEMD_INTERFACE, "StartUnit");
Matt Spinler882ce952017-10-05 16:12:41 -0500121
122 method.append(POWEROFF_TARGET);
123 method.append("replace");
124
125 bus.call_noreply(method);
126}
Matt Spinler48b4a432017-08-04 11:57:37 -0500127
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500128} // namespace util
129} // namespace power
130} // namespace witherspoon