xref: /openbmc/phosphor-gpio-monitor/presence/gpio_presence.hpp (revision cf33c593266d1a4fbdf952e1243cddded3920905)
1 #pragma once
2 #include "evdev.hpp"
3 
4 #include <systemd/sd-event.h>
5 
6 #include <sdbusplus/bus.hpp>
7 
8 #include <cstdlib>
9 #include <filesystem>
10 #include <string>
11 
12 namespace phosphor
13 {
14 namespace gpio
15 {
16 namespace presence
17 {
18 
19 static constexpr auto deviceField = 0;
20 static constexpr auto pathField = 1;
21 using Device = std::string;
22 using Path = std::filesystem::path;
23 using Driver = std::tuple<Device, Path>;
24 using Interface = std::string;
25 
26 /** @class Presence
27  *  @brief Responsible for determining and monitoring presence,
28  *  by monitoring GPIO state changes, of inventory items and
29  *  updating D-Bus accordingly.
30  */
31 class Presence : public Evdev
32 {
33     using Property = std::string;
34     using Value = std::variant<bool, std::string>;
35     // Association between property and its value
36     using PropertyMap = std::map<Property, Value>;
37     using Interface = std::string;
38     // Association between interface and the D-Bus property
39     using InterfaceMap = std::map<Interface, PropertyMap>;
40     using Object = sdbusplus::message::object_path;
41     // Association between object and the interface
42     using ObjectMap = std::map<Object, InterfaceMap>;
43 
44   public:
45     Presence() = delete;
46     ~Presence() = default;
47     Presence(const Presence&) = delete;
48     Presence& operator=(const Presence&) = delete;
49     Presence(Presence&&) = delete;
50     Presence& operator=(Presence&&) = delete;
51 
52     /** @brief Constructs Presence object.
53      *
54      *  @param[in] bus       - D-Bus bus Object
55      *  @param[in] inventory - Object path under inventory
56                                to display this inventory item
57      *  @param[in] path      - Device path to read for GPIO pin state
58                                to determine presence of inventory item
59      *  @param[in] key       - GPIO key to monitor
60      *  @param[in] name      - Pretty name of the inventory item
61      *  @param[in] event     - sd_event handler
62      *  @param[in] drivers   - list of device drivers to bind and unbind
63      *  @param[in] ifaces    - list of extra interfaces to associate with the
64      *                         inventory item
65      *  @param[in] handler   - IO callback handler. Defaults to one in this
66      *                        class
67      */
Presence(sdbusplus::bus_t & bus,const std::string & inventory,const std::string & path,const unsigned int key,const std::string & name,EventPtr & event,const std::vector<Driver> & drivers,const std::vector<Interface> & ifaces,sd_event_io_handler_t handler=Presence::processEvents)68     Presence(sdbusplus::bus_t& bus, const std::string& inventory,
69              const std::string& path, const unsigned int key,
70              const std::string& name, EventPtr& event,
71              const std::vector<Driver>& drivers,
72              const std::vector<Interface>& ifaces,
73              sd_event_io_handler_t handler = Presence::processEvents) :
74         Evdev(path, key, event, handler, true), bus(bus), inventory(inventory),
75         name(name), drivers(drivers), ifaces(ifaces)
76     {
77         // See if the environment (from configuration file?) has a
78         // DRIVER_BIND_DELAY_MS set.
79         if (char* envDelay = std::getenv("DRIVER_BIND_DELAY_MS"))
80         {
81             // DRIVER_BIND_DELAY_MS environment variable is set.
82             // Update the bind delay (in milliseconds) to the value from the
83             // environment.
84             delay = std::strtoull(envDelay, nullptr, 10);
85         }
86         determinePresence();
87     }
88 
89     /** @brief Callback handler when the FD has some activity on it
90      *
91      *  @param[in] es       - Populated event source
92      *  @param[in] fd       - Associated File descriptor
93      *  @param[in] revents  - Type of event
94      *  @param[in] userData - User data that was passed during registration
95      *
96      *  @return             - 0 or positive number on success and negative
97      *                        errno otherwise
98      */
99     static int processEvents(sd_event_source* es, int fd, uint32_t revents,
100                              void* userData);
101 
102   private:
103     /**
104      * @brief Update the present property for the inventory item.
105      *
106      * @param[in] present - What the present property should be set to.
107      */
108     void updateInventory(bool present);
109 
110     /**
111      * @brief Construct the inventory object map for the inventory item.
112      *
113      * @param[in] present - What the present property should be set to.
114      *
115      * @return The inventory object map to update inventory
116      */
117     ObjectMap getObjectMap(bool present);
118 
119     /** @brief Connection for sdbusplus bus */
120     sdbusplus::bus_t& bus;
121 
122     /**
123      * @brief Read the GPIO device to determine initial presence and set
124      *        present property at D-Bus path.
125      */
126     void determinePresence();
127 
128     /** @brief Object path under inventory to display this inventory item */
129     const std::string inventory;
130 
131     /** @brief Delay in milliseconds from present to bind device driver */
132     unsigned int delay = 0;
133 
134     /** @brief Pretty name of the inventory item*/
135     const std::string name;
136 
137     /** @brief Analyzes the GPIO event and update present property*/
138     void analyzeEvent();
139 
140     /** @brief  Vector of path and device tuples to bind/unbind*/
141     const std::vector<Driver> drivers;
142 
143     /** @brief  Vector of extra inventory interfaces to associate with the
144      *          inventory item
145      */
146     const std::vector<Interface> ifaces;
147 
148     /**
149      * @brief Binds or unbinds drivers
150      *
151      * Called when a presence change is detected to either
152      * bind the drivers for the new card or unbind them for
153      * the just removed card.  Operates on the drivers vector.
154      *
155      * Writes <device> to <path>/bind (or unbind)
156      *
157      * @param present - when true, will bind the drivers
158      *                  when false, will unbind them
159      */
160     void bindOrUnbindDrivers(bool present);
161 };
162 
163 /**
164  * @brief Get the service name from the mapper for the
165  *        interface and path passed in.
166  *
167  * @param[in] path      - The D-Bus path name
168  * @param[in] interface - The D-Bus interface name
169  * @param[in] bus       - The D-Bus bus object
170  *
171  * @return The service name
172  */
173 std::string getService(const std::string& path, const std::string& interface,
174                        sdbusplus::bus_t& bus);
175 
176 } // namespace presence
177 } // namespace gpio
178 } // namespace phosphor
179