adcsensor: improve bridge gpio handling
This commit improves bridge gpio handling using name based gpio line
access and polarity setting support.
Tested: P3VBAT sensor reading worked correctly.
Change-Id: Iff174c52dba90cc068f4b5e527d4ab1c381817d0
Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 564fce2..60a608b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -151,6 +151,7 @@
add_executable (adcsensor src/ADCSensorMain.cpp ${ADC_SRC_FILES})
add_dependencies (adcsensor sdbusplus-project)
target_link_libraries (adcsensor ${SENSOR_LINK_LIBS})
+target_link_libraries (adcsensor gpiodcxx)
add_executable (cpusensor src/CPUSensorMain.cpp ${CPU_SRC_FILES})
add_dependencies (cpusensor sdbusplus-project)
diff --git a/include/ADCSensor.hpp b/include/ADCSensor.hpp
index b5a9e9a..e061138 100644
--- a/include/ADCSensor.hpp
+++ b/include/ADCSensor.hpp
@@ -1,10 +1,50 @@
#pragma once
#include <Thresholds.hpp>
+#include <gpiod.hpp>
#include <optional>
#include <sdbusplus/asio/object_server.hpp>
#include <sensor.hpp>
+class BridgeGpio
+{
+ public:
+ BridgeGpio(const std::string& name, const int polarity)
+ {
+ line = gpiod::find_line(name);
+ if (!line)
+ {
+ std::cerr << "Error finding gpio: " << name << "\n";
+ }
+ else
+ {
+ try
+ {
+ line.request({"adcsensor",
+ gpiod::line_request::DIRECTION_OUTPUT,
+ polarity == gpiod::line::ACTIVE_HIGH
+ ? 0
+ : gpiod::line_request::FLAG_ACTIVE_LOW});
+ }
+ catch (std::system_error&)
+ {
+ std::cerr << "Error requesting gpio: " << name << "\n";
+ }
+ }
+ }
+
+ void set(int value)
+ {
+ if (line)
+ {
+ line.set_value(value);
+ }
+ }
+
+ private:
+ gpiod::line line;
+};
+
class ADCSensor : public Sensor
{
public:
@@ -15,7 +55,7 @@
std::vector<thresholds::Threshold>&& thresholds,
const double scaleFactor, PowerState readState,
const std::string& sensorConfiguration,
- std::optional<int> bridgeGpio);
+ std::optional<BridgeGpio> bridgeGpio);
~ADCSensor();
private:
@@ -26,7 +66,7 @@
std::string path;
int errCount;
double scaleFactor;
- std::optional<int> bridgeGpio;
+ std::optional<BridgeGpio> bridgeGpio;
PowerState readState;
thresholds::ThresholdTimer thresholdTimer;
void setupRead(void);
diff --git a/src/ADCSensor.cpp b/src/ADCSensor.cpp
index 2141ac4..ab1481b 100644
--- a/src/ADCSensor.cpp
+++ b/src/ADCSensor.cpp
@@ -37,24 +37,6 @@
static constexpr double roundFactor = 10000; // 3 decimal places
static constexpr double maxReading = 20;
static constexpr double minReading = 0;
-static constexpr const char* sysGpioPath = "/sys/class/gpio/gpio";
-static constexpr const char* postfixValue = "/value";
-
-void setGpio(int gpioN, int value)
-{
- std::string device = sysGpioPath + std::to_string(gpioN) + postfixValue;
- std::fstream gpioFile;
-
- gpioFile.open(device, std::ios::out);
-
- if (!gpioFile.good())
- {
- std::cerr << "Error opening device " << device << "\n";
- return;
- }
- gpioFile << std::to_string(value);
- gpioFile.close();
-}
ADCSensor::ADCSensor(const std::string& path,
sdbusplus::asio::object_server& objectServer,
@@ -63,7 +45,7 @@
std::vector<thresholds::Threshold>&& _thresholds,
const double scaleFactor, PowerState readState,
const std::string& sensorConfiguration,
- std::optional<int> bridgeGpio) :
+ std::optional<BridgeGpio> bridgeGpio) :
Sensor(boost::replace_all_copy(sensorName, " ", "_"),
std::move(_thresholds), sensorConfiguration,
"xyz.openbmc_project.Configuration.ADC", maxReading, minReading),
@@ -111,7 +93,7 @@
{
if (bridgeGpio.has_value())
{
- setGpio(*bridgeGpio, 1);
+ (*bridgeGpio).set(1);
// In case a channel has a bridge circuit,we have to turn the bridge on
// prior to reading a value at least for one scan cycle to get a valid
// value. Guarantee that the HW signal can be stable, the HW signal
@@ -191,7 +173,7 @@
inputDev.close();
if (bridgeGpio.has_value())
{
- setGpio(*bridgeGpio, 0);
+ (*bridgeGpio).set(0);
}
int fd = open(path.c_str(), O_RDONLY);
if (fd <= 0)
diff --git a/src/ADCSensorMain.cpp b/src/ADCSensorMain.cpp
index 188aad9..8a88244 100644
--- a/src/ADCSensorMain.cpp
+++ b/src/ADCSensorMain.cpp
@@ -230,21 +230,41 @@
}
}
- auto findBridgeGpio = baseConfiguration->second.find("BridgeGpio");
- std::optional<int> gpioNum;
-
- if (findBridgeGpio != baseConfiguration->second.end())
+ std::optional<BridgeGpio> bridgeGpio;
+ for (const SensorBaseConfiguration& suppConfig : *sensorData)
{
- int gpioPin =
- std::visit(VariantToIntVisitor(), findBridgeGpio->second);
- gpioNum = static_cast<std::optional<int>>(gpioPin);
+ if (suppConfig.first.find("BridgeGpio") != std::string::npos)
+ {
+ auto findName = suppConfig.second.find("Name");
+ if (findName != suppConfig.second.end())
+ {
+ std::string gpioName =
+ std::visit(VariantToStringVisitor(), findName->second);
+
+ int polarity = gpiod::line::ACTIVE_HIGH;
+ auto findPolarity = suppConfig.second.find("Polarity");
+ if (findPolarity != suppConfig.second.end())
+ {
+ if (std::string("Low") ==
+ std::visit(VariantToStringVisitor(),
+ findPolarity->second))
+ {
+ polarity = gpiod::line::ACTIVE_LOW;
+ }
+ }
+ bridgeGpio = BridgeGpio(gpioName, polarity);
+ }
+
+ break;
+ }
}
+
auto& sensor = sensors[sensorName];
sensor = nullptr;
sensor = std::make_unique<ADCSensor>(
path.string(), objectServer, dbusConnection, io, sensorName,
std::move(sensorThresholds), scaleFactor, readState, *interfacePath,
- gpioNum);
+ bridgeGpio);
}
}