1 #pragma once
2 
3 #include <phosphor-logging/elog.hpp>
4 #include <phosphor-logging/log.hpp>
5 #include <sdbusplus/bus.hpp>
6 
7 #include <string>
8 
9 namespace witherspoon
10 {
11 namespace power
12 {
13 namespace util
14 {
15 
16 constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
17 constexpr auto SYSTEMD_ROOT = "/org/freedesktop/systemd1";
18 constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
19 constexpr auto POWEROFF_TARGET = "obmc-chassis-hard-poweroff@0.target";
20 constexpr auto PROPERTY_INTF = "org.freedesktop.DBus.Properties";
21 
22 /**
23  * @brief Get the service name from the mapper for the
24  *        interface and path passed in.
25  *
26  * @param[in] path - the D-Bus path name
27  * @param[in] interface - the D-Bus interface name
28  * @param[in] bus - the D-Bus object
29  *
30  * @return The service name
31  */
32 std::string getService(const std::string& path, const std::string& interface,
33                        sdbusplus::bus_t& bus);
34 
35 /**
36  * @brief Read a D-Bus property
37  *
38  * @param[in] interface - the interface the property is on
39  * @param[in] propertName - the name of the property
40  * @param[in] path - the D-Bus path
41  * @param[in] service - the D-Bus service
42  * @param[in] bus - the D-Bus object
43  * @param[out] value - filled in with the property value
44  */
45 template <typename T>
getProperty(const std::string & interface,const std::string & propertyName,const std::string & path,const std::string & service,sdbusplus::bus_t & bus,T & value)46 void getProperty(const std::string& interface, const std::string& propertyName,
47                  const std::string& path, const std::string& service,
48                  sdbusplus::bus_t& bus, T& value)
49 {
50     std::variant<T> property;
51 
52     auto method = bus.new_method_call(service.c_str(), path.c_str(),
53                                       PROPERTY_INTF, "Get");
54 
55     method.append(interface, propertyName);
56 
57     auto reply = bus.call(method);
58 
59     reply.read(property);
60     value = std::get<T>(property);
61 }
62 
63 /**
64  * @brief Write a D-Bus property
65  *
66  * @param[in] interface - the interface the property is on
67  * @param[in] propertName - the name of the property
68  * @param[in] path - the D-Bus path
69  * @param[in] service - the D-Bus service
70  * @param[in] bus - the D-Bus object
71  * @param[in] value - the value to set the property to
72  */
73 template <typename T>
setProperty(const std::string & interface,const std::string & propertyName,const std::string & path,const std::string & service,sdbusplus::bus_t & bus,T & value)74 void setProperty(const std::string& interface, const std::string& propertyName,
75                  const std::string& path, const std::string& service,
76                  sdbusplus::bus_t& bus, T& value)
77 {
78     std::variant<T> propertyValue(value);
79 
80     auto method = bus.new_method_call(service.c_str(), path.c_str(),
81                                       PROPERTY_INTF, "Set");
82 
83     method.append(interface, propertyName, propertyValue);
84 
85     auto reply = bus.call(method);
86 }
87 
88 /**
89  * Logs an error and powers off the system.
90  *
91  * @tparam T - error that will be logged before the power off
92  * @param[in] bus - D-Bus object
93  */
94 template <typename T>
powerOff(sdbusplus::bus_t & bus)95 void powerOff(sdbusplus::bus_t& bus)
96 {
97     phosphor::logging::report<T>();
98 
99     auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
100                                       SYSTEMD_INTERFACE, "StartUnit");
101 
102     method.append(POWEROFF_TARGET);
103     method.append("replace");
104 
105     bus.call_noreply(method);
106 }
107 
108 } // namespace util
109 } // namespace power
110 } // namespace witherspoon
111