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