summaryrefslogtreecommitdiffstats
path: root/presence/gpio_presence.hpp
blob: 834a17149ee38a522f649a1290e53966bb745f48 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#pragma once
#include "evdev.hpp"

#include <systemd/sd-event.h>

#include <experimental/filesystem>
#include <string>

namespace phosphor
{
namespace gpio
{
namespace presence
{

static constexpr auto deviceField = 0;
static constexpr auto pathField = 1;
using Device = std::string;
using Path = std::experimental::filesystem::path;
using Driver = std::tuple<Device, Path>;

/** @class Presence
 *  @brief Responsible for determining and monitoring presence,
 *  by monitoring GPIO state changes, of inventory items and
 *  updating D-Bus accordingly.
 */
class Presence : public Evdev
{

    using Property = std::string;
    using Value = sdbusplus::message::variant<bool, std::string>;
    // Association between property and its value
    using PropertyMap = std::map<Property, Value>;
    using Interface = std::string;
    // Association between interface and the D-Bus property
    using InterfaceMap = std::map<Interface, PropertyMap>;
    using Object = sdbusplus::message::object_path;
    // Association between object and the interface
    using ObjectMap = std::map<Object, InterfaceMap>;

  public:
    Presence() = delete;
    ~Presence() = default;
    Presence(const Presence&) = delete;
    Presence& operator=(const Presence&) = delete;
    Presence(Presence&&) = delete;
    Presence& operator=(Presence&&) = delete;

    /** @brief Constructs Presence object.
     *
     *  @param[in] bus       - D-Bus bus Object
     *  @param[in] inventory - Object path under inventory
                               to display this inventory item
     *  @param[in] path      - Device path to read for GPIO pin state
                               to determine presence of inventory item
     *  @param[in] key       - GPIO key to monitor
     *  @param[in] name      - Pretty name of the inventory item
     *  @param[in] event     - sd_event handler
     *  @param[in] drivers   - list of device drivers to bind and unbind
     *  @param[in] handler   - IO callback handler. Defaults to one in this
     *                        class
     */
    Presence(sdbusplus::bus::bus& bus, const std::string& inventory,
             const std::string& path, const unsigned int key,
             const std::string& name, EventPtr& event,
             const std::vector<Driver>& drivers,
             sd_event_io_handler_t handler = Presence::processEvents) :
        Evdev(path, key, event, handler, true),
        bus(bus), inventory(inventory), name(name), drivers(drivers)
    {
        determinePresence();
    }

    /** @brief Callback handler when the FD has some activity on it
     *
     *  @param[in] es       - Populated event source
     *  @param[in] fd       - Associated File descriptor
     *  @param[in] revents  - Type of event
     *  @param[in] userData - User data that was passed during registration
     *
     *  @return             - 0 or positive number on success and negative
     *                        errno otherwise
     */
    static int processEvents(sd_event_source* es, int fd, uint32_t revents,
                             void* userData);

  private:
    /**
     * @brief Update the present property for the inventory item.
     *
     * @param[in] present - What the present property should be set to.
     */
    void updateInventory(bool present);

    /**
     * @brief Construct the inventory object map for the inventory item.
     *
     * @param[in] present - What the present property should be set to.
     *
     * @return The inventory object map to update inventory
     */
    ObjectMap getObjectMap(bool present);

    /** @brief Connection for sdbusplus bus */
    sdbusplus::bus::bus& bus;

    /**
     * @brief Read the GPIO device to determine initial presence and set
     *        present property at D-Bus path.
     */
    void determinePresence();

    /** @brief Object path under inventory to display this inventory item */
    const std::string inventory;

    /** @brief Pretty name of the inventory item*/
    const std::string name;

    /** @brief Analyzes the GPIO event and update present property*/
    void analyzeEvent();

    /** @brief  Vector of path and device tuples to bind/unbind*/
    const std::vector<Driver> drivers;

    /**
     * @brief Binds or unbinds drivers
     *
     * Called when a presence change is detected to either
     * bind the drivers for the new card or unbind them for
     * the just removed card.  Operates on the drivers vector.
     *
     * Writes <device> to <path>/bind (or unbind)
     *
     * @param present - when true, will bind the drivers
     *                  when false, will unbind them
     */
    void bindOrUnbindDrivers(bool present);
};

/**
 * @brief Get the service name from the mapper for the
 *        interface and path passed in.
 *
 * @param[in] path      - The D-Bus path name
 * @param[in] interface - The D-Bus interface name
 * @param[in] bus       - The D-Bus bus object
 *
 * @return The service name
 */
std::string getService(const std::string& path, const std::string& interface,
                       sdbusplus::bus::bus& bus);

} // namespace presence
} // namespace gpio
} // namespace phosphor
OpenPOWER on IntegriCloud