1974c916eSMatt Spinler #pragma once 2974c916eSMatt Spinler 3974c916eSMatt Spinler #include <phosphor-logging/log.hpp> 4882ce956SMatt Spinler #include <phosphor-logging/elog.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 */ 31974c916eSMatt Spinler std::string getService(const std::string& path, 32974c916eSMatt Spinler const std::string& interface, 33974c916eSMatt Spinler sdbusplus::bus::bus& bus); 34974c916eSMatt Spinler 35974c916eSMatt Spinler /** 36974c916eSMatt Spinler * @brief Read a D-Bus property 37974c916eSMatt Spinler * 38974c916eSMatt Spinler * @param[in] interface - the interface the property is on 39974c916eSMatt Spinler * @param[in] propertName - the name of the property 40974c916eSMatt Spinler * @param[in] path - the D-Bus path 41974c916eSMatt Spinler * @param[in] service - the D-Bus service 42974c916eSMatt Spinler * @param[in] bus - the D-Bus object 43974c916eSMatt Spinler * @param[out] value - filled in with the property value 44974c916eSMatt Spinler */ 45974c916eSMatt Spinler template<typename T> 46974c916eSMatt Spinler void getProperty(const std::string& interface, 47974c916eSMatt Spinler const std::string& propertyName, 48974c916eSMatt Spinler const std::string& path, 49974c916eSMatt Spinler const std::string& service, 50974c916eSMatt Spinler sdbusplus::bus::bus& bus, 51974c916eSMatt Spinler T& value) 52974c916eSMatt Spinler { 53974c916eSMatt Spinler sdbusplus::message::variant<T> property; 54974c916eSMatt Spinler 55974c916eSMatt Spinler auto method = bus.new_method_call(service.c_str(), 56974c916eSMatt Spinler path.c_str(), 57974c916eSMatt Spinler PROPERTY_INTF, 58974c916eSMatt Spinler "Get"); 59974c916eSMatt Spinler 60974c916eSMatt Spinler method.append(interface, propertyName); 61974c916eSMatt Spinler 62974c916eSMatt Spinler auto reply = bus.call(method); 63974c916eSMatt Spinler if (reply.is_method_error()) 64974c916eSMatt Spinler { 65974c916eSMatt Spinler using namespace phosphor::logging; 66974c916eSMatt Spinler log<level::ERR>("Error in property get call", 67974c916eSMatt Spinler entry("PATH=%s", path.c_str()), 68974c916eSMatt Spinler entry("PROPERTY=%s", propertyName.c_str())); 69882ce956SMatt Spinler 70974c916eSMatt Spinler // TODO openbmc/openbmc#851 - Once available, throw returned error 71974c916eSMatt Spinler throw std::runtime_error("Error in property get call"); 72974c916eSMatt Spinler } 73974c916eSMatt Spinler 74974c916eSMatt Spinler reply.read(property); 75974c916eSMatt Spinler value = sdbusplus::message::variant_ns::get<T>(property); 76974c916eSMatt Spinler } 77974c916eSMatt Spinler 7848b4a430SMatt Spinler /** 79*0a4f519bSBrandon Wyman * @brief Write a D-Bus property 80*0a4f519bSBrandon Wyman * 81*0a4f519bSBrandon Wyman * @param[in] interface - the interface the property is on 82*0a4f519bSBrandon Wyman * @param[in] propertName - the name of the property 83*0a4f519bSBrandon Wyman * @param[in] path - the D-Bus path 84*0a4f519bSBrandon Wyman * @param[in] service - the D-Bus service 85*0a4f519bSBrandon Wyman * @param[in] bus - the D-Bus object 86*0a4f519bSBrandon Wyman * @param[in] value - the value to set the property to 87*0a4f519bSBrandon Wyman */ 88*0a4f519bSBrandon Wyman template<typename T> 89*0a4f519bSBrandon Wyman void setProperty(const std::string& interface, 90*0a4f519bSBrandon Wyman const std::string& propertyName, 91*0a4f519bSBrandon Wyman const std::string& path, 92*0a4f519bSBrandon Wyman const std::string& service, 93*0a4f519bSBrandon Wyman sdbusplus::bus::bus& bus, 94*0a4f519bSBrandon Wyman T& value) 95*0a4f519bSBrandon Wyman { 96*0a4f519bSBrandon Wyman sdbusplus::message::variant<T> propertyValue(value); 97*0a4f519bSBrandon Wyman 98*0a4f519bSBrandon Wyman auto method = bus.new_method_call(service.c_str(), 99*0a4f519bSBrandon Wyman path.c_str(), 100*0a4f519bSBrandon Wyman PROPERTY_INTF, 101*0a4f519bSBrandon Wyman "Set"); 102*0a4f519bSBrandon Wyman 103*0a4f519bSBrandon Wyman method.append(interface, propertyName, propertyValue); 104*0a4f519bSBrandon Wyman 105*0a4f519bSBrandon Wyman auto reply = bus.call(method); 106*0a4f519bSBrandon Wyman if (reply.is_method_error()) 107*0a4f519bSBrandon Wyman { 108*0a4f519bSBrandon Wyman using namespace phosphor::logging; 109*0a4f519bSBrandon Wyman log<level::ERR>("Error in property set call", 110*0a4f519bSBrandon Wyman entry("SERVICE=%s", service.c_str()), 111*0a4f519bSBrandon Wyman entry("PATH=%s", path.c_str()), 112*0a4f519bSBrandon Wyman entry("PROPERTY=%s", propertyName.c_str())); 113*0a4f519bSBrandon Wyman 114*0a4f519bSBrandon Wyman // TODO openbmc/openbmc#851 - Once available, throw returned error 115*0a4f519bSBrandon Wyman throw std::runtime_error("Error in property set call"); 116*0a4f519bSBrandon Wyman } 117*0a4f519bSBrandon Wyman 118*0a4f519bSBrandon Wyman } 119*0a4f519bSBrandon Wyman 120*0a4f519bSBrandon Wyman /** 121882ce956SMatt Spinler * Logs an error and powers off the system. 12248b4a430SMatt Spinler * 123882ce956SMatt Spinler * @tparam T - error that will be logged before the power off 12448b4a430SMatt Spinler * @param[in] bus - D-Bus object 12548b4a430SMatt Spinler */ 126882ce956SMatt Spinler template<typename T> 127882ce956SMatt Spinler void powerOff(sdbusplus::bus::bus& bus) 128882ce956SMatt Spinler { 129882ce956SMatt Spinler phosphor::logging::report<T>(); 130882ce956SMatt Spinler 131882ce956SMatt Spinler auto method = bus.new_method_call(SYSTEMD_SERVICE, 132882ce956SMatt Spinler SYSTEMD_ROOT, 133882ce956SMatt Spinler SYSTEMD_INTERFACE, 134882ce956SMatt Spinler "StartUnit"); 135882ce956SMatt Spinler 136882ce956SMatt Spinler method.append(POWEROFF_TARGET); 137882ce956SMatt Spinler method.append("replace"); 138882ce956SMatt Spinler 139882ce956SMatt Spinler bus.call_noreply(method); 140882ce956SMatt Spinler } 14148b4a430SMatt Spinler 142974c916eSMatt Spinler } 143974c916eSMatt Spinler } 144974c916eSMatt Spinler } 145