1b1e329a6SBrad Bishop #pragma once
2b1e329a6SBrad Bishop 
33d6d3182SPatrick Venture #include <phosphor-logging/elog-errors.hpp>
43d6d3182SPatrick Venture #include <phosphor-logging/elog.hpp>
513e3df60SGeorge Liu #include <phosphor-logging/lg2.hpp>
6b1e329a6SBrad Bishop #include <sdbusplus/bus.hpp>
76f04b229SGeorge Liu #include <sdbusplus/exception.hpp>
8b1e329a6SBrad Bishop #include <sdbusplus/message.hpp>
9b1e329a6SBrad Bishop #include <xyz/openbmc_project/Common/error.hpp>
10b1e329a6SBrad Bishop 
113fe976ccSGeorge Liu #include <string>
123fe976ccSGeorge Liu 
13b1e329a6SBrad Bishop namespace util
14b1e329a6SBrad Bishop {
15b1e329a6SBrad Bishop namespace detail
16b1e329a6SBrad Bishop {
17b1e329a6SBrad Bishop namespace errors = sdbusplus::xyz::openbmc_project::Common::Error;
18b1e329a6SBrad Bishop } // namespace detail
19b1e329a6SBrad Bishop 
20b1e329a6SBrad Bishop /** @brief Alias for PropertiesChanged signal callbacks. */
21b1e329a6SBrad Bishop template <typename... T>
2235b4f337SPatrick Williams using Properties = std::map<std::string, std::variant<T...>>;
23b1e329a6SBrad Bishop 
24b1e329a6SBrad Bishop namespace sdbusplus
25b1e329a6SBrad Bishop {
26b1e329a6SBrad Bishop 
27b1e329a6SBrad Bishop /** @brief Get the bus connection. */
28b1e329a6SBrad Bishop static auto& getBus() __attribute__((pure));
getBus()29b1e329a6SBrad Bishop static auto& getBus()
30b1e329a6SBrad Bishop {
31b1e329a6SBrad Bishop     static auto bus = ::sdbusplus::bus::new_default();
32b1e329a6SBrad Bishop     return bus;
33b1e329a6SBrad Bishop }
34b1e329a6SBrad Bishop 
35b1e329a6SBrad Bishop /** @brief Invoke a method. */
36b1e329a6SBrad Bishop template <typename... Args>
callMethod(::sdbusplus::bus_t & bus,const std::string & busName,const std::string & path,const std::string & interface,const std::string & method,Args &&...args)37413a4857SPatrick Williams static auto callMethod(::sdbusplus::bus_t& bus, const std::string& busName,
38d1eac88dSBrad Bishop                        const std::string& path, const std::string& interface,
39d1eac88dSBrad Bishop                        const std::string& method, Args&&... args)
40b1e329a6SBrad Bishop {
41d1eac88dSBrad Bishop     auto reqMsg = bus.new_method_call(busName.c_str(), path.c_str(),
42d1eac88dSBrad Bishop                                       interface.c_str(), method.c_str());
43b1e329a6SBrad Bishop     reqMsg.append(std::forward<Args>(args)...);
446f04b229SGeorge Liu     try
45b1e329a6SBrad Bishop     {
466f04b229SGeorge Liu         return bus.call(reqMsg);
476f04b229SGeorge Liu     }
486f04b229SGeorge Liu     catch (const std::exception& e)
496f04b229SGeorge Liu     {
506f04b229SGeorge Liu         lg2::error("Failed to invoke DBus method: {PATH}, {INTF}, {METHOD}",
5113e3df60SGeorge Liu                    "PATH", path, "INTF", interface, "METHOD", method);
52b1e329a6SBrad Bishop         phosphor::logging::elog<detail::errors::InternalFailure>();
53b1e329a6SBrad Bishop     }
54b1e329a6SBrad Bishop }
55b1e329a6SBrad Bishop 
56b1e329a6SBrad Bishop /** @brief Invoke a method. */
57b1e329a6SBrad Bishop template <typename... Args>
callMethod(const std::string & busName,const std::string & path,const std::string & interface,const std::string & method,Args &&...args)58d1eac88dSBrad Bishop static auto callMethod(const std::string& busName, const std::string& path,
59d1eac88dSBrad Bishop                        const std::string& interface, const std::string& method,
60b1e329a6SBrad Bishop                        Args&&... args)
61b1e329a6SBrad Bishop {
62d1eac88dSBrad Bishop     return callMethod(getBus(), busName, path, interface, method,
63b1e329a6SBrad Bishop                       std::forward<Args>(args)...);
64b1e329a6SBrad Bishop }
65b1e329a6SBrad Bishop 
66b1e329a6SBrad Bishop /** @brief Invoke a method and read the response. */
67b1e329a6SBrad Bishop template <typename Ret, typename... Args>
68d1eac88dSBrad Bishop static auto
callMethodAndRead(::sdbusplus::bus_t & bus,const std::string & busName,const std::string & path,const std::string & interface,const std::string & method,Args &&...args)69413a4857SPatrick Williams     callMethodAndRead(::sdbusplus::bus_t& bus, const std::string& busName,
70d1eac88dSBrad Bishop                       const std::string& path, const std::string& interface,
71d1eac88dSBrad Bishop                       const std::string& method, Args&&... args)
72b1e329a6SBrad Bishop {
73413a4857SPatrick Williams     ::sdbusplus::message_t respMsg = callMethod<Args...>(
74d1eac88dSBrad Bishop         bus, busName, path, interface, method, std::forward<Args>(args)...);
75b1e329a6SBrad Bishop     Ret resp;
76b1e329a6SBrad Bishop     respMsg.read(resp);
77b1e329a6SBrad Bishop     return resp;
78b1e329a6SBrad Bishop }
79b1e329a6SBrad Bishop 
80b1e329a6SBrad Bishop /** @brief Invoke a method and read the response. */
81b1e329a6SBrad Bishop template <typename Ret, typename... Args>
callMethodAndRead(const std::string & busName,const std::string & path,const std::string & interface,const std::string & method,Args &&...args)82d1eac88dSBrad Bishop static auto callMethodAndRead(const std::string& busName,
83b1e329a6SBrad Bishop                               const std::string& path,
84b1e329a6SBrad Bishop                               const std::string& interface,
85d1eac88dSBrad Bishop                               const std::string& method, Args&&... args)
86b1e329a6SBrad Bishop {
87d1eac88dSBrad Bishop     return callMethodAndRead<Ret>(getBus(), busName, path, interface, method,
88b1e329a6SBrad Bishop                                   std::forward<Args>(args)...);
89b1e329a6SBrad Bishop }
90b1e329a6SBrad Bishop 
91b1e329a6SBrad Bishop /** @brief Get service from the mapper. */
getService(::sdbusplus::bus_t & bus,const std::string & path,const std::string & interface)92413a4857SPatrick Williams static auto getService(::sdbusplus::bus_t& bus, const std::string& path,
93b1e329a6SBrad Bishop                        const std::string& interface)
94b1e329a6SBrad Bishop {
95b1e329a6SBrad Bishop     using namespace std::literals::string_literals;
96b1e329a6SBrad Bishop     using GetObject = std::map<std::string, std::vector<std::string>>;
97b1e329a6SBrad Bishop 
98b1e329a6SBrad Bishop     auto mapperResp = callMethodAndRead<GetObject>(
99d1eac88dSBrad Bishop         bus, "xyz.openbmc_project.ObjectMapper"s,
100b1e329a6SBrad Bishop         "/xyz/openbmc_project/object_mapper"s,
101d1eac88dSBrad Bishop         "xyz.openbmc_project.ObjectMapper"s, "GetObject"s, path,
102b1e329a6SBrad Bishop         GetObject::mapped_type{interface});
103b1e329a6SBrad Bishop 
104b1e329a6SBrad Bishop     if (mapperResp.empty())
105b1e329a6SBrad Bishop     {
10613e3df60SGeorge Liu         lg2::error("Object not found. {PATH}, {INTF}", "PATH", path, "INTF",
10713e3df60SGeorge Liu                    interface);
108b1e329a6SBrad Bishop         phosphor::logging::elog<detail::errors::InternalFailure>();
109b1e329a6SBrad Bishop     }
110b1e329a6SBrad Bishop     return mapperResp.begin()->first;
111b1e329a6SBrad Bishop }
112b1e329a6SBrad Bishop 
113b1e329a6SBrad Bishop /** @brief Get a property without mapper lookup. */
114b1e329a6SBrad Bishop template <typename Property>
getProperty(::sdbusplus::bus_t & bus,const std::string & busName,const std::string & path,const std::string & interface,const std::string & property)115413a4857SPatrick Williams static auto getProperty(::sdbusplus::bus_t& bus, const std::string& busName,
116d1eac88dSBrad Bishop                         const std::string& path, const std::string& interface,
117b1e329a6SBrad Bishop                         const std::string& property)
118b1e329a6SBrad Bishop {
119b1e329a6SBrad Bishop     using namespace std::literals::string_literals;
120b1e329a6SBrad Bishop 
121*c5fe26a6SPatrick Williams     auto msg = callMethod(bus, busName, path,
122*c5fe26a6SPatrick Williams                           "org.freedesktop.DBus.Properties"s, "Get"s, interface,
123*c5fe26a6SPatrick Williams                           property);
12435b4f337SPatrick Williams     ::std::variant<Property> value;
125b1e329a6SBrad Bishop     msg.read(value);
12634ef1e52SPatrick Williams     return std::get<Property>(value);
127b1e329a6SBrad Bishop }
128b1e329a6SBrad Bishop 
129b1e329a6SBrad Bishop /** @brief Get a property without mapper lookup. */
130b1e329a6SBrad Bishop template <typename Property>
getProperty(const std::string & busName,const std::string & path,const std::string & interface,const std::string & property)131d1eac88dSBrad Bishop static auto getProperty(const std::string& busName, const std::string& path,
132b1e329a6SBrad Bishop                         const std::string& interface,
133b1e329a6SBrad Bishop                         const std::string& property)
134b1e329a6SBrad Bishop {
135d1eac88dSBrad Bishop     return getProperty<Property>(getBus(), busName, path, interface, property);
136b1e329a6SBrad Bishop }
137b1e329a6SBrad Bishop 
138b1e329a6SBrad Bishop /** @brief Get a property with mapper lookup. */
139b1e329a6SBrad Bishop template <typename Property>
getProperty(::sdbusplus::bus_t & bus,const std::string & path,const std::string & interface,const std::string & property)140413a4857SPatrick Williams static auto getProperty(::sdbusplus::bus_t& bus, const std::string& path,
141b1e329a6SBrad Bishop                         const std::string& interface,
142b1e329a6SBrad Bishop                         const std::string& property)
143b1e329a6SBrad Bishop {
144d1eac88dSBrad Bishop     return getProperty<Property>(bus, getService(bus, path, interface), path,
145d1eac88dSBrad Bishop                                  interface, property);
146b1e329a6SBrad Bishop }
147b1e329a6SBrad Bishop 
148b1e329a6SBrad Bishop /** @brief Get a property with mapper lookup. */
149b1e329a6SBrad Bishop template <typename Property>
getProperty(const std::string & path,const std::string & interface,const std::string & property)150d1eac88dSBrad Bishop static auto getProperty(const std::string& path, const std::string& interface,
151b1e329a6SBrad Bishop                         const std::string& property)
152b1e329a6SBrad Bishop {
153d1eac88dSBrad Bishop     return getProperty<Property>(getBus(), path, interface, property);
154b1e329a6SBrad Bishop }
155b1e329a6SBrad Bishop 
156b1e329a6SBrad Bishop } // namespace sdbusplus
157b1e329a6SBrad Bishop } // namespace util
158