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