1 #pragma once
2 #include "util_base.hpp"
3 #include "utility.hpp"
4 #include "xyz/openbmc_project/Common/error.hpp"
5 
6 #include <fmt/format.h>
7 
8 #include <gpiod.hpp>
9 #include <phosphor-logging/elog-errors.hpp>
10 #include <phosphor-logging/elog.hpp>
11 #include <phosphor-logging/log.hpp>
12 
13 #include <bitset>
14 
15 namespace phosphor::power::psu
16 {
17 
18 class Util : public UtilBase
19 {
20   public:
21     bool getPresence(sdbusplus::bus::bus& bus,
22                      const std::string& invpath) const override
23     {
24         bool present = false;
25 
26         // Use getProperty utility function to get presence status.
27         util::getProperty(INVENTORY_IFACE, PRESENT_PROP, invpath,
28                           INVENTORY_MGR_IFACE, bus, present);
29 
30         return present;
31     }
32 
33     void setPresence(sdbusplus::bus::bus& bus, const std::string& invpath,
34                      bool present, const std::string& name) const override
35     {
36         using InternalFailure =
37             sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
38         using Property = std::string;
39         using Value = std::variant<bool, std::string>;
40         // Association between property and its value
41         using PropertyMap = std::map<Property, Value>;
42         PropertyMap invProp;
43 
44         invProp.emplace("Present", present);
45         invProp.emplace("PrettyName", name);
46 
47         using Interface = std::string;
48         // Association between interface and the D-Bus property map
49         using InterfaceMap = std::map<Interface, PropertyMap>;
50         InterfaceMap invIntf;
51         invIntf.emplace("xyz.openbmc_project.Inventory.Item",
52                         std::move(invProp));
53 
54         Interface extraIface = "xyz.openbmc_project.Inventory.Item.PowerSupply";
55 
56         invIntf.emplace(extraIface, PropertyMap());
57 
58         using Object = sdbusplus::message::object_path;
59         // Association between object and the interface map
60         using ObjectMap = std::map<Object, InterfaceMap>;
61         ObjectMap invObj;
62         invObj.emplace(std::move(invpath), std::move(invIntf));
63 
64         using namespace phosphor::logging;
65         log<level::INFO>(fmt::format("Updating inventory present property. "
66                                      "present:{} invpath:{} name:{}",
67                                      present, invpath, name)
68                              .c_str());
69 
70         try
71         {
72             auto invService = phosphor::power::util::getService(
73                 INVENTORY_OBJ_PATH, INVENTORY_MGR_IFACE, bus);
74 
75             // Update inventory
76             auto invMsg =
77                 bus.new_method_call(invService.c_str(), INVENTORY_OBJ_PATH,
78                                     INVENTORY_MGR_IFACE, "Notify");
79             invMsg.append(std::move(invObj));
80             auto invMgrResponseMsg = bus.call(invMsg);
81         }
82         catch (const std::exception& e)
83         {
84             log<level::ERR>(
85                 fmt::format(
86                     "Error in inventory manager call to update inventory: {}",
87                     e.what())
88                     .c_str());
89             elog<InternalFailure>();
90         }
91     }
92 };
93 
94 std::unique_ptr<GPIOInterfaceBase> createGPIO(const std::string& namedGpio);
95 
96 class GPIOInterface : public GPIOInterfaceBase
97 {
98   public:
99     GPIOInterface() = delete;
100     virtual ~GPIOInterface() = default;
101     GPIOInterface(const GPIOInterface&) = default;
102     GPIOInterface& operator=(const GPIOInterface&) = default;
103     GPIOInterface(GPIOInterface&&) = default;
104     GPIOInterface& operator=(GPIOInterface&&) = default;
105 
106     /**
107      * Constructor
108      *
109      * @param[in] namedGpio - The string for the gpio-line-name
110      */
111     GPIOInterface(const std::string& namedGpio);
112 
113     static std::unique_ptr<GPIOInterfaceBase>
114         createGPIO(const std::string& namedGpio);
115 
116     /**
117      * @brief Attempts to read the state of the GPIO line.
118      *
119      * Throws an exception if line not found, request line fails, or get_value
120      * from line fails.
121      *
122      * @return 1 for active (low/present), 0 for not active (high/not present).
123      */
124     int read() override;
125 
126     /**
127      * @brief Attempts to set the state of the GPIO line to the specified value.
128      *
129      * Throws an exception if line not found, request line fails, or set_value
130      * to line fails.
131      *
132      * @param[in] value - The value to set the state of the GPIO line, 1 or 0.
133      * @param[in] flags - Additional line request flags as defined in gpiod.hpp.
134      */
135     void write(int value, std::bitset<32> flags) override;
136 
137     /**
138      * @brief Returns the name of the GPIO, if not empty.
139      */
140     std::string getName() const override;
141 
142   private:
143     gpiod::line line;
144 };
145 
146 } // namespace phosphor::power::psu
147