blob: e8f68ca0e2cbe4c4d1fbef732cce02883721ad8f [file] [log] [blame]
Gunnar Mills72639152017-06-22 15:06:21 -05001#pragma once
Gunnar Mills5f101102017-06-29 13:07:39 -05002#include <string>
Gunnar Mills765725e2017-07-06 14:17:44 -05003#include <systemd/sd-event.h>
Gunnar Mills5f101102017-06-29 13:07:39 -05004#include <libevdev/libevdev.h>
5#include "file.hpp"
Gunnar Mills72639152017-06-22 15:06:21 -05006
7namespace phosphor
8{
9namespace gpio
10{
11namespace presence
12{
13
Gunnar Mills765725e2017-07-06 14:17:44 -050014/* Need a custom deleter for freeing up sd_event */
15struct EventDeleter
16{
17 void operator()(sd_event* event) const
18 {
19 event = sd_event_unref(event);
20 }
21};
22using EventPtr = std::unique_ptr<sd_event, EventDeleter>;
23
24/* Need a custom deleter for freeing up sd_event_source */
25struct EventSourceDeleter
26{
27 void operator()(sd_event_source* eventSource) const
28 {
29 eventSource = sd_event_source_unref(eventSource);
30 }
31};
32using EventSourcePtr = std::unique_ptr<sd_event_source, EventSourceDeleter>;
33
Gunnar Mills5f101102017-06-29 13:07:39 -050034/* Need a custom deleter for freeing up evdev struct */
35struct FreeEvDev
36{
37 void operator()(struct libevdev* device) const
38 {
39 libevdev_free(device);
40 }
41};
42using EvdevPtr = std::unique_ptr<struct libevdev, FreeEvDev>;
43
44/** @class Presence
45 * @brief Responsible for determining and monitoring presence of
46 * inventory items and updating D-Bus accordingly.
47 */
48class Presence
49{
50
Gunnar Mills80292bb2017-07-05 16:34:51 -050051 using Property = std::string;
52 using Value = sdbusplus::message::variant<bool, std::string>;
53 // Association between property and its value
54 using PropertyMap = std::map<Property, Value>;
55 using Interface = std::string;
56 // Association between interface and the D-Bus property
57 using InterfaceMap = std::map<Interface, PropertyMap>;
58 using Object = sdbusplus::message::object_path;
59 // Association between object and the interface
60 using ObjectMap = std::map<Object, InterfaceMap>;
61
Gunnar Mills5f101102017-06-29 13:07:39 -050062 public:
63 Presence() = delete;
64 ~Presence() = default;
65 Presence(const Presence&) = delete;
66 Presence& operator=(const Presence&) = delete;
67 Presence(Presence&&) = delete;
68 Presence& operator=(Presence&&) = delete;
69
70 /** @brief Constructs Presence object.
71 *
Gunnar Mills80292bb2017-07-05 16:34:51 -050072 * @param[in] bus - D-Bus bus Object
Gunnar Mills5f101102017-06-29 13:07:39 -050073 * @param[in] inventory - Object path under inventory
74 to display this inventory item
75 * @param[in] path - Device path to read for GPIO pin state
76 to determine presence of inventory item
77 * @param[in] key - GPIO key to monitor
78 * @param[in] name - Pretty name of the inventory item
Gunnar Mills765725e2017-07-06 14:17:44 -050079 * @param[in] event - sd_event handler
80 * @param[in] handler - IO callback handler. Defaults to one in this
81 * class
Gunnar Mills5f101102017-06-29 13:07:39 -050082 */
Gunnar Mills80292bb2017-07-05 16:34:51 -050083 Presence(sdbusplus::bus::bus& bus,
84 const std::string& inventory,
Gunnar Mills5f101102017-06-29 13:07:39 -050085 const std::string& path,
86 const unsigned int key,
Gunnar Mills765725e2017-07-06 14:17:44 -050087 const std::string& name,
88 EventPtr& event,
89 sd_event_io_handler_t handler = Presence::processEvents) :
Gunnar Mills80292bb2017-07-05 16:34:51 -050090 bus(bus),
Gunnar Mills5f101102017-06-29 13:07:39 -050091 inventory(inventory),
92 path(path),
93 key(key),
94 name(name),
Gunnar Mills765725e2017-07-06 14:17:44 -050095 event(event),
96 callbackHandler(handler),
Gunnar Mills5f101102017-06-29 13:07:39 -050097 fd(openDevice())
Gunnar Mills765725e2017-07-06 14:17:44 -050098
Gunnar Mills5f101102017-06-29 13:07:39 -050099 {
100 initEvDev();
101 determinePresence();
Gunnar Mills765725e2017-07-06 14:17:44 -0500102 // Register callback handler when FD has some data
103 registerCallback();
Gunnar Mills5f101102017-06-29 13:07:39 -0500104 }
105
Gunnar Mills765725e2017-07-06 14:17:44 -0500106 /** @brief Callback handler when the FD has some activity on it
107 *
108 * @param[in] es - Populated event source
109 * @param[in] fd - Associated File descriptor
110 * @param[in] revents - Type of event
111 * @param[in] userData - User data that was passed during registration
112 *
113 * @return - 0 or positive number on success and negative
114 * errno otherwise
115 */
116 static int processEvents(sd_event_source* es, int fd,
117 uint32_t revents, void* userData);
118
Gunnar Mills5f101102017-06-29 13:07:39 -0500119 private:
120 /**
Gunnar Mills80292bb2017-07-05 16:34:51 -0500121 * @brief Update the present property for the inventory item.
122 *
123 * @param[in] present - What the present property should be set to.
124 */
125 void updateInventory(bool present);
126
127 /**
128 * @brief Construct the inventory object map for the inventory item.
129 *
130 * @param[in] present - What the present property should be set to.
131 *
132 * @return The inventory object map to update inventory
133 */
134 ObjectMap getObjectMap(bool present);
135
136 /** @brief Connection for sdbusplus bus */
137 sdbusplus::bus::bus& bus;
138
139 /**
Gunnar Mills5f101102017-06-29 13:07:39 -0500140 * @brief Read the GPIO device to determine initial presence and set
141 * present property at D-Bus path.
142 **/
143 void determinePresence();
144
145 /** @brief Object path under inventory to display this inventory item */
146 const std::string inventory;
147
148 /** @brief Device path to read for GPIO pin state
149 to determine presence of inventory item */
150 const std::string path;
151
152 /** @brief GPIO key to monitor */
153 const unsigned int key;
154
155 /** @brief Pretty name of the inventory item*/
156 const std::string name;
157
158 /** @brief Event structure */
159 EvdevPtr devicePtr;
160
Gunnar Mills765725e2017-07-06 14:17:44 -0500161 /** @brief Monitor to sd_event */
162 EventPtr& event;
163
164 /** @brief Callback handler when the FD has some data */
165 sd_event_io_handler_t callbackHandler;
166
167 /** @brief event source */
168 EventSourcePtr eventSource;
169
Gunnar Mills5f101102017-06-29 13:07:39 -0500170 /** @brief Opens the device and populates the descriptor */
171 int openDevice();
172
Gunnar Mills765725e2017-07-06 14:17:44 -0500173 /** @brief attaches FD to events and sets up callback handler */
174 void registerCallback();
175
Gunnar Mills5f101102017-06-29 13:07:39 -0500176 /** @brief File descriptor manager */
177 FileDescriptor fd;
178
Gunnar Mills765725e2017-07-06 14:17:44 -0500179 /** @brief Analyzes the GPIO event and update present property*/
180 void analyzeEvent();
181
Gunnar Mills5f101102017-06-29 13:07:39 -0500182 /** @brief Initializes evdev handle with the fd */
183 void initEvDev();
184};
185
Gunnar Mills80292bb2017-07-05 16:34:51 -0500186/**
187 * @brief Get the service name from the mapper for the
188 * interface and path passed in.
189 *
190 * @param[in] path - The D-Bus path name
191 * @param[in] interface - The D-Bus interface name
192 * @param[in] bus - The D-Bus bus object
193 *
194 * @return The service name
195 */
196std::string getService(const std::string& path,
197 const std::string& interface,
198 sdbusplus::bus::bus& bus);
199
Gunnar Mills72639152017-06-22 15:06:21 -0500200} // namespace presence
201} // namespace gpio
202} // namespace phosphor
203