gpio-presence: Add function to bind/unbind drivers
The cards that this app is doing presence detection for
may have devices with drivers that need to be bound and
unbound when the card is added and removed, respectively.
The drivers to do this to will be passed into the app
on startup (in a future commit). Then when presence detect
changes the proper binds/unbinds will be done.
This commit adds the code in the Presence class to do so.
Change-Id: I32827e45b88ddb7586aba6b819cc591b49aa9c51
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
diff --git a/presence/Makefile.am b/presence/Makefile.am
index 7cc80d4..6c2e564 100644
--- a/presence/Makefile.am
+++ b/presence/Makefile.am
@@ -16,6 +16,7 @@
$(LIBEVDEV_CFLAGS)
phosphor_gpio_presence_LDADD = \
+ -lstdc++fs \
$(PHOSPHOR_LOGGING_LIBS) \
$(PHOSPHOR_DBUS_INTERFACES_LIBS) \
$(LIBEVDEV_LIBS)
diff --git a/presence/gpio_presence.cpp b/presence/gpio_presence.cpp
index b87e139..ecc4813 100644
--- a/presence/gpio_presence.cpp
+++ b/presence/gpio_presence.cpp
@@ -1,5 +1,6 @@
-#include <libevdev/libevdev.h>
#include <fcntl.h>
+#include <fstream>
+#include <libevdev/libevdev.h>
#include <phosphor-logging/elog.hpp>
#include <phosphor-logging/log.hpp>
#include <phosphor-logging/elog-errors.hpp>
@@ -128,6 +129,7 @@
present = true;
}
updateInventory(present);
+ bindOrUnbindDrivers(present);
}
}
}
@@ -173,6 +175,57 @@
"Error in inventory manager call to update inventory");
elog<InternalFailure>();
}
+
+}
+
+void Presence::bindOrUnbindDrivers(bool present)
+{
+ auto action = (present) ? "bind" : "unbind";
+
+ for (auto& driver : drivers)
+ {
+ auto path = std::get<pathField>(driver) / action;
+ auto device = std::get<deviceField>(driver);
+
+ if (present)
+ {
+ log<level::INFO>(
+ "Binding a device driver",
+ entry("PATH=%s", path.c_str()),
+ entry("DEVICE=%s", device.c_str()));
+ }
+ else
+ {
+ log<level::INFO>(
+ "Unbinding a device driver",
+ entry("PATH=%s", path.c_str()),
+ entry("DEVICE=%s", device.c_str()));
+ }
+
+ std::ofstream file;
+
+ file.exceptions(
+ std::ofstream::failbit |
+ std::ofstream::badbit |
+ std::ofstream::eofbit);
+
+ try
+ {
+ file.open(path);
+ file << device;
+ file.close();
+ }
+ catch (std::exception& e)
+ {
+ auto err = errno;
+
+ log<level::ERR>("Failed binding or unbinding a device "
+ "after a card was removed or added",
+ entry("PATH=%s", path.c_str()),
+ entry("DEVICE=%s", device.c_str()),
+ entry("ERRNO=%d", err));
+ }
+ }
}
diff --git a/presence/gpio_presence.hpp b/presence/gpio_presence.hpp
index 986dbe6..b5feddd 100644
--- a/presence/gpio_presence.hpp
+++ b/presence/gpio_presence.hpp
@@ -1,4 +1,5 @@
#pragma once
+#include <experimental/filesystem>
#include <string>
#include <systemd/sd-event.h>
#include "evdev.hpp"
@@ -10,6 +11,12 @@
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
@@ -47,6 +54,7 @@
* @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
*/
@@ -56,11 +64,13 @@
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)
+ name(name),
+ drivers(drivers)
{
determinePresence();
}
@@ -101,7 +111,7 @@
/**
* @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 */
@@ -112,6 +122,23 @@
/** @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);
};
/**
diff --git a/presence/main.cpp b/presence/main.cpp
index 6116540..5808c34 100644
--- a/presence/main.cpp
+++ b/presence/main.cpp
@@ -39,6 +39,10 @@
options.usage(argv);
}
+ std::vector<Driver> driverList;
+
+ //TODO: next commit, fill in driverList
+
auto bus = sdbusplus::bus::new_default();
auto rc = 0;
sd_event* event = nullptr;
@@ -52,7 +56,8 @@
event = nullptr;
auto name = options["name"];
- Presence presence(bus, inventory, path, std::stoul(key), name, eventP);
+ Presence presence(
+ bus, inventory, path, std::stoul(key), name, eventP, driverList);
while (true)
{