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