Add support for GPIO polling for presence detection
The current PresenceGpio implementation uses event driven detection by
using the gpioLine.event_read method to detect GPIO signal changes, and
then to determine the presence status.
This commit will add support for a PollingPresenceGpio for GPIOs that
do not support events. It will use a pollTimer to periodically read the
GPIO status (every second).
The monitorPresence() function should be called to initiate the
monitoring of the GPIO.
TEST: Tested with multiple GPIOs including disabling to simulate
removing of device and enable to re-detect device. Unable to test Event
driven GPIO due to no hw available.
Change-Id: If46e884ad237dfe909a9373773c8302a0844ac90
Signed-off-by: Chris Cain <cjcain@us.ibm.com>
diff --git a/src/fan/FanMain.cpp b/src/fan/FanMain.cpp
index 736d07d..33074b6 100644
--- a/src/fan/FanMain.cpp
+++ b/src/fan/FanMain.cpp
@@ -282,193 +282,194 @@
sensorsChanged,
size_t retries = 0)
{
- auto getter = std::make_shared<GetSensorConfiguration>(
- dbusConnection,
- [&io, &objectServer, &tachSensors, &pwmSensors, &presenceGpios,
- &dbusConnection,
- sensorsChanged](const ManagedObjectType& sensorConfigurations) {
- bool firstScan = sensorsChanged == nullptr;
- std::vector<fs::path> paths;
- if (!findFiles(fs::path("/sys/class/hwmon"), R"(fan\d+_input)",
- paths))
+ auto getter = std::make_shared<
+ GetSensorConfiguration>(dbusConnection, [&io, &objectServer,
+ &tachSensors, &pwmSensors,
+ &presenceGpios,
+ &dbusConnection,
+ sensorsChanged](
+ const ManagedObjectType&
+ sensorConfigurations) {
+ bool firstScan = sensorsChanged == nullptr;
+ std::vector<fs::path> paths;
+ if (!findFiles(fs::path("/sys/class/hwmon"), R"(fan\d+_input)", paths))
+ {
+ std::cerr << "No fan sensors in system\n";
+ return;
+ }
+
+ // iterate through all found fan sensors, and try to match them with
+ // configuration
+ for (const auto& path : paths)
+ {
+ std::smatch match;
+ std::string pathStr = path.string();
+
+ std::regex_search(pathStr, match, inputRegex);
+ std::string indexStr = *(match.begin() + 1);
+
+ fs::path directory = path.parent_path();
+ FanTypes fanType = getFanType(directory);
+ std::string cfgIntf = configInterfaceName(sensorTypes[fanType]);
+
+ // convert to 0 based
+ size_t index = std::stoul(indexStr) - 1;
+
+ const char* baseType = nullptr;
+ const SensorData* sensorData = nullptr;
+ const std::string* interfacePath = nullptr;
+ const SensorBaseConfiguration* baseConfiguration = nullptr;
+ for (const auto& [path, cfgData] : sensorConfigurations)
{
- std::cerr << "No fan sensors in system\n";
- return;
- }
-
- // iterate through all found fan sensors, and try to match them with
- // configuration
- for (const auto& path : paths)
- {
- std::smatch match;
- std::string pathStr = path.string();
-
- std::regex_search(pathStr, match, inputRegex);
- std::string indexStr = *(match.begin() + 1);
-
- fs::path directory = path.parent_path();
- FanTypes fanType = getFanType(directory);
- std::string cfgIntf = configInterfaceName(sensorTypes[fanType]);
-
- // convert to 0 based
- size_t index = std::stoul(indexStr) - 1;
-
- const char* baseType = nullptr;
- const SensorData* sensorData = nullptr;
- const std::string* interfacePath = nullptr;
- const SensorBaseConfiguration* baseConfiguration = nullptr;
- for (const auto& [path, cfgData] : sensorConfigurations)
+ // find the base of the configuration to see if indexes
+ // match
+ auto sensorBaseFind = cfgData.find(cfgIntf);
+ if (sensorBaseFind == cfgData.end())
{
- // find the base of the configuration to see if indexes
- // match
- auto sensorBaseFind = cfgData.find(cfgIntf);
- if (sensorBaseFind == cfgData.end())
+ continue;
+ }
+
+ baseConfiguration = &(*sensorBaseFind);
+ interfacePath = &path.str;
+ baseType = sensorTypes[fanType];
+
+ auto findIndex = baseConfiguration->second.find("Index");
+ if (findIndex == baseConfiguration->second.end())
+ {
+ std::cerr << baseConfiguration->first << " missing index\n";
+ continue;
+ }
+ unsigned int configIndex = std::visit(
+ VariantToUnsignedIntVisitor(), findIndex->second);
+ if (configIndex != index)
+ {
+ continue;
+ }
+ if (fanType == FanTypes::aspeed ||
+ fanType == FanTypes::nuvoton || fanType == FanTypes::hpe)
+ {
+ // there will be only 1 aspeed or nuvoton or hpe sensor
+ // object in sysfs, we found the fan
+ sensorData = &cfgData;
+ break;
+ }
+ if (fanType == FanTypes::i2c)
+ {
+ std::string deviceName =
+ fs::read_symlink(directory / "device").filename();
+
+ size_t bus = 0;
+ size_t addr = 0;
+ if (!getDeviceBusAddr(deviceName, bus, addr))
{
continue;
}
- baseConfiguration = &(*sensorBaseFind);
- interfacePath = &path.str;
- baseType = sensorTypes[fanType];
+ auto findBus = baseConfiguration->second.find("Bus");
+ auto findAddress =
+ baseConfiguration->second.find("Address");
+ if (findBus == baseConfiguration->second.end() ||
+ findAddress == baseConfiguration->second.end())
+ {
+ std::cerr << baseConfiguration->first
+ << " missing bus or address\n";
+ continue;
+ }
+ unsigned int configBus = std::visit(
+ VariantToUnsignedIntVisitor(), findBus->second);
+ unsigned int configAddress = std::visit(
+ VariantToUnsignedIntVisitor(), findAddress->second);
- auto findIndex = baseConfiguration->second.find("Index");
- if (findIndex == baseConfiguration->second.end())
+ if (configBus == bus && configAddress == addr)
{
- std::cerr
- << baseConfiguration->first << " missing index\n";
- continue;
- }
- unsigned int configIndex = std::visit(
- VariantToUnsignedIntVisitor(), findIndex->second);
- if (configIndex != index)
- {
- continue;
- }
- if (fanType == FanTypes::aspeed ||
- fanType == FanTypes::nuvoton ||
- fanType == FanTypes::hpe)
- {
- // there will be only 1 aspeed or nuvoton or hpe sensor
- // object in sysfs, we found the fan
sensorData = &cfgData;
break;
}
- if (fanType == FanTypes::i2c)
+ }
+ }
+ if (sensorData == nullptr)
+ {
+ std::cerr << "failed to find match for " << path.string()
+ << "\n";
+ continue;
+ }
+
+ auto findSensorName = baseConfiguration->second.find("Name");
+
+ if (findSensorName == baseConfiguration->second.end())
+ {
+ std::cerr << "could not determine configuration name for "
+ << path.string() << "\n";
+ continue;
+ }
+ std::string sensorName =
+ std::get<std::string>(findSensorName->second);
+
+ // on rescans, only update sensors we were signaled by
+ auto findSensor = tachSensors.find(sensorName);
+ if (!firstScan && findSensor != tachSensors.end())
+ {
+ bool found = false;
+ for (auto it = sensorsChanged->begin();
+ it != sensorsChanged->end(); it++)
+ {
+ if (it->ends_with(findSensor->second->name))
{
- std::string deviceName =
- fs::read_symlink(directory / "device").filename();
-
- size_t bus = 0;
- size_t addr = 0;
- if (!getDeviceBusAddr(deviceName, bus, addr))
- {
- continue;
- }
-
- auto findBus = baseConfiguration->second.find("Bus");
- auto findAddress =
- baseConfiguration->second.find("Address");
- if (findBus == baseConfiguration->second.end() ||
- findAddress == baseConfiguration->second.end())
- {
- std::cerr << baseConfiguration->first
- << " missing bus or address\n";
- continue;
- }
- unsigned int configBus = std::visit(
- VariantToUnsignedIntVisitor(), findBus->second);
- unsigned int configAddress = std::visit(
- VariantToUnsignedIntVisitor(), findAddress->second);
-
- if (configBus == bus && configAddress == addr)
- {
- sensorData = &cfgData;
- break;
- }
+ sensorsChanged->erase(it);
+ findSensor->second = nullptr;
+ found = true;
+ break;
}
}
- if (sensorData == nullptr)
+ if (!found)
{
- std::cerr
- << "failed to find match for " << path.string() << "\n";
continue;
}
+ }
+ std::vector<thresholds::Threshold> sensorThresholds;
+ if (!parseThresholdsFromConfig(*sensorData, sensorThresholds))
+ {
+ std::cerr << "error populating thresholds for " << sensorName
+ << "\n";
+ }
- auto findSensorName = baseConfiguration->second.find("Name");
+ auto presenceConfig =
+ sensorData->find(cfgIntf + std::string(".Presence"));
- if (findSensorName == baseConfiguration->second.end())
+ std::shared_ptr<PresenceGpio> presenceGpio(nullptr);
+
+ // presence sensors are optional
+ if (presenceConfig != sensorData->end())
+ {
+ auto findPolarity = presenceConfig->second.find("Polarity");
+ auto findPinName = presenceConfig->second.find("PinName");
+
+ if (findPinName == presenceConfig->second.end() ||
+ findPolarity == presenceConfig->second.end())
{
- std::cerr << "could not determine configuration name for "
- << path.string() << "\n";
- continue;
+ std::cerr << "Malformed Presence Configuration\n";
}
- std::string sensorName =
- std::get<std::string>(findSensorName->second);
-
- // on rescans, only update sensors we were signaled by
- auto findSensor = tachSensors.find(sensorName);
- if (!firstScan && findSensor != tachSensors.end())
+ else
{
- bool found = false;
- for (auto it = sensorsChanged->begin();
- it != sensorsChanged->end(); it++)
+ bool inverted =
+ std::get<std::string>(findPolarity->second) == "Low";
+ const auto* pinName =
+ std::get_if<std::string>(&findPinName->second);
+
+ if (pinName != nullptr)
{
- if (it->ends_with(findSensor->second->name))
+ auto findPresenceGpio = presenceGpios.find(*pinName);
+ if (findPresenceGpio != presenceGpios.end())
{
- sensorsChanged->erase(it);
- findSensor->second = nullptr;
- found = true;
- break;
- }
- }
- if (!found)
- {
- continue;
- }
- }
- std::vector<thresholds::Threshold> sensorThresholds;
- if (!parseThresholdsFromConfig(*sensorData, sensorThresholds))
- {
- std::cerr << "error populating thresholds for "
- << sensorName << "\n";
- }
-
- auto presenceConfig =
- sensorData->find(cfgIntf + std::string(".Presence"));
-
- std::shared_ptr<PresenceGpio> presenceGpio(nullptr);
-
- // presence sensors are optional
- if (presenceConfig != sensorData->end())
- {
- auto findPolarity = presenceConfig->second.find("Polarity");
- auto findPinName = presenceConfig->second.find("PinName");
-
- if (findPinName == presenceConfig->second.end() ||
- findPolarity == presenceConfig->second.end())
- {
- std::cerr << "Malformed Presence Configuration\n";
- }
- else
- {
- bool inverted = std::get<std::string>(
- findPolarity->second) == "Low";
- const auto* pinName =
- std::get_if<std::string>(&findPinName->second);
-
- if (pinName != nullptr)
- {
- auto findPresenceGpio =
- presenceGpios.find(*pinName);
- if (findPresenceGpio != presenceGpios.end())
+ auto p = findPresenceGpio->second.lock();
+ if (p)
{
- auto p = findPresenceGpio->second.lock();
- if (p)
- {
- presenceGpio = p;
- }
+ presenceGpio = p;
}
- if (!presenceGpio)
+ }
+ if (!presenceGpio)
+ {
+ try
{
presenceGpio =
std::make_shared<EventPresenceGpio>(
@@ -476,130 +477,135 @@
io);
presenceGpios[*pinName] = presenceGpio;
}
- }
- else
- {
- std::cerr
- << "Malformed Presence pinName for sensor "
- << sensorName << " \n";
- }
- }
- }
- std::optional<RedundancySensor>* redundancy = nullptr;
- if (fanType == FanTypes::aspeed)
- {
- redundancy = &systemRedundancy;
- }
-
- PowerState powerState =
- getPowerState(baseConfiguration->second);
-
- constexpr double defaultMaxReading = 25000;
- constexpr double defaultMinReading = 0;
- std::pair<double, double> limits =
- std::make_pair(defaultMinReading, defaultMaxReading);
-
- auto connector =
- sensorData->find(cfgIntf + std::string(".Connector"));
-
- std::optional<std::string> led;
- std::string pwmName;
- fs::path pwmPath;
-
- // The Mutable parameter is optional, defaulting to false
- bool isValueMutable = false;
- if (connector != sensorData->end())
- {
- auto findPwm = connector->second.find("Pwm");
- if (findPwm != connector->second.end())
- {
- size_t pwm = std::visit(VariantToUnsignedIntVisitor(),
- findPwm->second);
- if (!findPwmPath(directory, pwm, pwmPath))
- {
- std::cerr << "Connector for " << sensorName
- << " no pwm channel found!\n";
- continue;
- }
-
- fs::path pwmEnableFile =
- "pwm" + std::to_string(pwm + 1) + "_enable";
- fs::path enablePath =
- pwmPath.parent_path() / pwmEnableFile;
- enablePwm(enablePath);
-
- /* use pwm name override if found in configuration else
- * use default */
- auto findOverride = connector->second.find("PwmName");
- if (findOverride != connector->second.end())
- {
- pwmName = std::visit(VariantToStringVisitor(),
- findOverride->second);
- }
- else
- {
- pwmName = "Pwm_" + std::to_string(pwm + 1);
- }
-
- // Check PWM sensor mutability
- auto findMutable = connector->second.find("Mutable");
- if (findMutable != connector->second.end())
- {
- const auto* ptrMutable =
- std::get_if<bool>(&(findMutable->second));
- if (ptrMutable != nullptr)
+ catch (const std::system_error& e)
{
- isValueMutable = *ptrMutable;
+ std::cerr
+ << "Failed to create GPIO monitor object for "
+ << *pinName << " / " << sensorName << ": "
+ << e.what() << "\n";
}
}
}
else
{
+ std::cerr << "Malformed Presence pinName for sensor "
+ << sensorName << " \n";
+ }
+ }
+ }
+ std::optional<RedundancySensor>* redundancy = nullptr;
+ if (fanType == FanTypes::aspeed)
+ {
+ redundancy = &systemRedundancy;
+ }
+
+ PowerState powerState = getPowerState(baseConfiguration->second);
+
+ constexpr double defaultMaxReading = 25000;
+ constexpr double defaultMinReading = 0;
+ std::pair<double, double> limits =
+ std::make_pair(defaultMinReading, defaultMaxReading);
+
+ auto connector =
+ sensorData->find(cfgIntf + std::string(".Connector"));
+
+ std::optional<std::string> led;
+ std::string pwmName;
+ fs::path pwmPath;
+
+ // The Mutable parameter is optional, defaulting to false
+ bool isValueMutable = false;
+ if (connector != sensorData->end())
+ {
+ auto findPwm = connector->second.find("Pwm");
+ if (findPwm != connector->second.end())
+ {
+ size_t pwm = std::visit(VariantToUnsignedIntVisitor(),
+ findPwm->second);
+ if (!findPwmPath(directory, pwm, pwmPath))
+ {
std::cerr << "Connector for " << sensorName
- << " missing pwm!\n";
+ << " no pwm channel found!\n";
+ continue;
}
- auto findLED = connector->second.find("LED");
- if (findLED != connector->second.end())
+ fs::path pwmEnableFile =
+ "pwm" + std::to_string(pwm + 1) + "_enable";
+ fs::path enablePath = pwmPath.parent_path() / pwmEnableFile;
+ enablePwm(enablePath);
+
+ /* use pwm name override if found in configuration else
+ * use default */
+ auto findOverride = connector->second.find("PwmName");
+ if (findOverride != connector->second.end())
{
- const auto* ledName =
- std::get_if<std::string>(&(findLED->second));
- if (ledName == nullptr)
+ pwmName = std::visit(VariantToStringVisitor(),
+ findOverride->second);
+ }
+ else
+ {
+ pwmName = "Pwm_" + std::to_string(pwm + 1);
+ }
+
+ // Check PWM sensor mutability
+ auto findMutable = connector->second.find("Mutable");
+ if (findMutable != connector->second.end())
+ {
+ const auto* ptrMutable =
+ std::get_if<bool>(&(findMutable->second));
+ if (ptrMutable != nullptr)
{
- std::cerr << "Wrong format for LED of "
- << sensorName << "\n";
- }
- else
- {
- led = *ledName;
+ isValueMutable = *ptrMutable;
}
}
}
-
- findLimits(limits, baseConfiguration);
-
- enableFanInput(path);
-
- auto& tachSensor = tachSensors[sensorName];
- tachSensor = nullptr;
- tachSensor = std::make_shared<TachSensor>(
- path.string(), baseType, objectServer, dbusConnection,
- presenceGpio, redundancy, io, sensorName,
- std::move(sensorThresholds), *interfacePath, limits,
- powerState, led);
- tachSensor->setupRead();
-
- if (!pwmPath.empty() && fs::exists(pwmPath) &&
- (pwmSensors.count(pwmPath) == 0U))
+ else
{
- pwmSensors[pwmPath] = std::make_unique<PwmSensor>(
- pwmName, pwmPath, dbusConnection, objectServer,
- *interfacePath, "Fan", isValueMutable);
+ std::cerr
+ << "Connector for " << sensorName << " missing pwm!\n";
+ }
+
+ auto findLED = connector->second.find("LED");
+ if (findLED != connector->second.end())
+ {
+ const auto* ledName =
+ std::get_if<std::string>(&(findLED->second));
+ if (ledName == nullptr)
+ {
+ std::cerr
+ << "Wrong format for LED of " << sensorName << "\n";
+ }
+ else
+ {
+ led = *ledName;
+ }
}
}
- createRedundancySensor(tachSensors, dbusConnection, objectServer);
- });
+ findLimits(limits, baseConfiguration);
+
+ enableFanInput(path);
+
+ auto& tachSensor = tachSensors[sensorName];
+ tachSensor = nullptr;
+ tachSensor = std::make_shared<TachSensor>(
+ path.string(), baseType, objectServer, dbusConnection,
+ presenceGpio, redundancy, io, sensorName,
+ std::move(sensorThresholds), *interfacePath, limits, powerState,
+ led);
+ tachSensor->setupRead();
+
+ if (!pwmPath.empty() && fs::exists(pwmPath) &&
+ (pwmSensors.count(pwmPath) == 0U))
+ {
+ pwmSensors[pwmPath] = std::make_unique<PwmSensor>(
+ pwmName, pwmPath, dbusConnection, objectServer,
+ *interfacePath, "Fan", isValueMutable);
+ }
+ }
+
+ createRedundancySensor(tachSensors, dbusConnection, objectServer);
+ });
getter->getConfiguration(
std::vector<std::string>{sensorTypes.begin(), sensorTypes.end()},
retries);
diff --git a/src/fan/PresenceGpio.cpp b/src/fan/PresenceGpio.cpp
index 6c528d7..d917c82 100644
--- a/src/fan/PresenceGpio.cpp
+++ b/src/fan/PresenceGpio.cpp
@@ -20,20 +20,36 @@
#include <boost/asio/posix/stream_descriptor.hpp>
#include <gpiod.hpp>
+#include <chrono>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <system_error>
+static constexpr unsigned int pollIntervalSec = 1;
+
+PresenceGpio::PresenceGpio(const std::string& deviceType,
+ const std::string& deviceName,
+ const std::string& gpioName) :
+ deviceType(deviceType), deviceName(deviceName), gpioName(gpioName)
+{
+ gpioLine = gpiod::find_line(gpioName);
+ if (!gpioLine)
+ {
+ std::cerr << "Error requesting gpio: " << gpioName << "\n";
+ throw std::runtime_error("Failed to find GPIO " + gpioName);
+ }
+}
+
PresenceGpio::~PresenceGpio()
{
gpioLine.release();
}
-void PresenceGpio::updateAndTracePresence()
+void PresenceGpio::updateAndTracePresence(int newValue)
{
- status = (gpioLine.get_value() != 0);
+ status = (newValue != 0);
if (status)
{
logPresent(deviceName);
@@ -45,41 +61,32 @@
}
EventPresenceGpio::EventPresenceGpio(
- const std::string& iDeviceType, const std::string& iDeviceName,
+ const std::string& deviceType, const std::string& deviceName,
const std::string& gpioName, bool inverted, boost::asio::io_context& io) :
- PresenceGpio(iDeviceType, iDeviceName), gpioFd(io)
+ PresenceGpio(deviceType, deviceName, gpioName), gpioFd(io)
{
- gpioLine = gpiod::find_line(gpioName);
- if (!gpioLine)
- {
- std::cerr << "Error requesting gpio: " << gpioName << "\n";
- return;
- }
-
try
{
gpioLine.request(
{deviceType + "Sensor", gpiod::line_request::EVENT_BOTH_EDGES,
inverted ? gpiod::line_request::FLAG_ACTIVE_LOW : 0});
- updateAndTracePresence();
-
- int gpioLineFd = gpioLine.event_get_fd();
- if (gpioLineFd < 0)
- {
- std::cerr << "Failed to get " << gpioName << " fd\n";
- throw std::runtime_error("Failed to get GPIO fd " + gpioName);
- }
-
- gpioFd.assign(gpioLineFd);
+ updateAndTracePresence(gpioLine.get_value());
}
catch (const std::system_error& e)
{
std::cerr << "Error reading gpio " << gpioName << ": " << e.what()
<< "\n";
- return;
+ throw std::runtime_error("Failed to read GPIO fd " + gpioName);
}
- monitorPresence();
+ int gpioLineFd = gpioLine.event_get_fd();
+ if (gpioLineFd < 0)
+ {
+ std::cerr << "Failed to get " << gpioName << " fd\n";
+ throw std::runtime_error("Failed to get GPIO fd " + gpioName);
+ }
+
+ gpioFd.assign(gpioLineFd);
}
void EventPresenceGpio::monitorPresence()
@@ -114,5 +121,65 @@
{
// Read is invoked when an edge event is detected by monitorPresence
gpioLine.event_read();
- updateAndTracePresence();
+ updateAndTracePresence(gpioLine.get_value());
+}
+
+PollingPresenceGpio::PollingPresenceGpio(
+ const std::string& deviceType, const std::string& deviceName,
+ const std::string& gpioName, bool inverted, boost::asio::io_context& io) :
+ PresenceGpio(deviceType, deviceName, gpioName), pollTimer(io)
+{
+ try
+ {
+ gpioLine.request(
+ {deviceType + "Sensor", gpiod::line_request::DIRECTION_INPUT,
+ inverted ? gpiod::line_request::FLAG_ACTIVE_LOW : 0});
+ updateAndTracePresence(gpioLine.get_value());
+ }
+ catch (const std::system_error& e)
+ {
+ std::cerr << "PollingPresenceGpio: Error reading gpio " << gpioName
+ << ": " << e.what() << "\n";
+ status = false;
+ throw std::runtime_error("Failed to get Polling GPIO fd " + gpioName);
+ }
+}
+
+inline void PollingPresenceGpio::pollTimerHandler(
+ const std::weak_ptr<PollingPresenceGpio>& weakRef,
+ const boost::system::error_code& ec)
+{
+ std::shared_ptr<PollingPresenceGpio> self = weakRef.lock();
+ if (!self)
+ {
+ std::cerr << "Failed to get lock for pollingPresenceGpio: "
+ << ec.message() << "\n";
+ return;
+ }
+ if (ec)
+ {
+ if (ec != boost::system::errc::bad_file_descriptor)
+ {
+ std::cerr << "GPIO polling timer failed for " << self->gpioName
+ << ": " << ec.what() << ")\n";
+ }
+ return;
+ }
+ self->monitorPresence();
+}
+
+void PollingPresenceGpio::monitorPresence()
+{
+ // Determine if the value has changed
+ int newStatus = gpioLine.get_value();
+ if (static_cast<int>(status) != newStatus)
+ {
+ updateAndTracePresence(newStatus);
+ }
+
+ std::weak_ptr<PollingPresenceGpio> weakRef = weak_from_this();
+ pollTimer.expires_after(std::chrono::seconds(pollIntervalSec));
+ pollTimer.async_wait([weakRef](const boost::system::error_code& ec) {
+ pollTimerHandler(weakRef, ec);
+ });
}
diff --git a/src/fan/PresenceGpio.hpp b/src/fan/PresenceGpio.hpp
index 54805cf..627270b 100644
--- a/src/fan/PresenceGpio.hpp
+++ b/src/fan/PresenceGpio.hpp
@@ -8,12 +8,13 @@
class PresenceGpio
{
public:
- PresenceGpio(const std::string& type, const std::string& name) :
- deviceType(type), deviceName(name) {};
+ PresenceGpio(const std::string& deviceType, const std::string& deviceName,
+ const std::string& gpioName);
PresenceGpio(const PresenceGpio&) = delete;
PresenceGpio& operator=(const PresenceGpio&) = delete;
virtual ~PresenceGpio() = 0;
+ virtual void monitorPresence() = 0;
bool isPresent() const
{
return status;
@@ -24,8 +25,7 @@
bool status = false;
std::string deviceType;
std::string deviceName;
-
- virtual void monitorPresence() = 0;
+ std::string gpioName;
void logPresent(const std::string& device)
{
@@ -43,7 +43,7 @@
"REDFISH_MESSAGE_ARGS", device);
}
- void updateAndTracePresence();
+ void updateAndTracePresence(int newValue);
};
class EventPresenceGpio :
@@ -51,14 +51,39 @@
public std::enable_shared_from_this<EventPresenceGpio>
{
public:
- EventPresenceGpio(const std::string& iDeviceType,
- const std::string& iDeviceName,
+ EventPresenceGpio(const std::string& deviceType,
+ const std::string& deviceName,
const std::string& gpioName, bool inverted,
boost::asio::io_context& io);
+ void monitorPresence() override;
+
private:
boost::asio::posix::stream_descriptor gpioFd;
- void monitorPresence() override;
void read();
};
+
+class PollingPresenceGpio :
+ public PresenceGpio,
+ public std::enable_shared_from_this<PollingPresenceGpio>
+{
+ public:
+ PollingPresenceGpio(const std::string& deviceType,
+ const std::string& deviceName,
+ const std::string& gpioName, bool inverted,
+ boost::asio::io_context& io);
+ ~PollingPresenceGpio() override
+ {
+ // GPIO no longer being used so release/remove
+ gpioLine.release();
+ }
+ void monitorPresence() override;
+
+ private:
+ boost::asio::steady_timer pollTimer;
+
+ static inline void
+ pollTimerHandler(const std::weak_ptr<PollingPresenceGpio>& weakRef,
+ const boost::system::error_code& ec);
+};
diff --git a/src/fan/TachSensor.cpp b/src/fan/TachSensor.cpp
index 7908488..10a34a4 100644
--- a/src/fan/TachSensor.cpp
+++ b/src/fan/TachSensor.cpp
@@ -78,6 +78,7 @@
if (presence)
{
+ presence->monitorPresence();
itemIface =
objectServer.add_interface("/xyz/openbmc_project/inventory/" + name,
"xyz.openbmc_project.Inventory.Item");