convert sysfs gpio usage to libgpiod
Updated Chassis Intrusion Sensor monitoring
to use pin name and gpiod APIs. Number based sysfs
framework is deprecated and replaced by descriptor
based gpiod framework. With named gpio pin,
code is more portable provided the device tree
defines GPIO pin name consistently.
This requires device tree change (227661) and
configuration file change (entity-manager/+/28350)
Tested:
Build and run changes together and verified chassis intrusion sensor
value gets updated correctly through D-Bus object.
Signed-off-by: ZhikuiRen <zhikui.ren@intel.com>
Change-Id: I03c50e32059936902432d5a8bc498dabb812ea5e
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 645a1a8..f9d6d31 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -181,6 +181,7 @@
add_dependencies (intrusionsensor sdbusplus-project)
target_link_libraries (intrusionsensor ${SENSOR_LINK_LIBS})
target_link_libraries (intrusionsensor i2c)
+target_link_libraries (intrusionsensor gpiodcxx)
add_executable (ipmbsensor src/IpmbSensor.cpp ${IPMB_SRC_FILES})
add_dependencies (ipmbsensor sdbusplus-project)
diff --git a/include/ChassisIntrusionSensor.hpp b/include/ChassisIntrusionSensor.hpp
index 651e768..f65ef33 100644
--- a/include/ChassisIntrusionSensor.hpp
+++ b/include/ChassisIntrusionSensor.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include <gpiod.hpp>
#include <memory>
#include <sdbusplus/asio/object_server.hpp>
#include <string>
@@ -20,7 +21,7 @@
~ChassisIntrusionSensor();
void start(IntrusionSensorType type, int busId, int slaveAddr,
- int gpioIndex, bool gpioInverted);
+ bool gpioInverted);
private:
std::shared_ptr<sdbusplus::asio::dbus_interface> mIface;
@@ -38,10 +39,10 @@
boost::asio::deadline_timer mPollTimer;
// valid if it is via GPIO
- int mGpioIndex;
bool mGpioInverted;
- boost::asio::ip::tcp::socket mInputDev;
- int mFd;
+ std::string mPinName = "CHASSIS_INTRUSION";
+ gpiod::line mGpioLine;
+ boost::asio::posix::stream_descriptor mGpioFd;
// common members
bool mOverridenState = false;
@@ -54,6 +55,6 @@
void pollSensorStatusByPch();
void readGpio();
void pollSensorStatusByGpio();
- void initGpioDeviceFile(const int index);
+ void initGpioDeviceFile();
int setSensorValue(const std::string& req, std::string& propertyValue);
};
diff --git a/include/Utils.hpp b/include/Utils.hpp
index d97ff9c..565656a 100644
--- a/include/Utils.hpp
+++ b/include/Utils.hpp
@@ -17,7 +17,6 @@
#include <variant>
#include <vector>
-constexpr const char* gpioPath = "/sys/class/gpio/";
const constexpr char* jsonStore = "/var/configuration/flattened.json";
const constexpr char* inventoryPath = "/xyz/openbmc_project/inventory";
const constexpr char* entityManagerName = "xyz.openbmc_project.EntityManager";
diff --git a/src/ChassisIntrusionSensor.cpp b/src/ChassisIntrusionSensor.cpp
index 60d0f0d..4b2327e 100644
--- a/src/ChassisIntrusionSensor.cpp
+++ b/src/ChassisIntrusionSensor.cpp
@@ -45,9 +45,6 @@
// Status bit field masks
const static constexpr size_t pchRegMaskIntrusion = 0x01;
-// gpio sysfs path
-constexpr const char* gpioPath = "/sys/class/gpio/";
-
void ChassisIntrusionSensor::updateValue(const std::string newValue)
{
// indicate that it is internal set call
@@ -168,45 +165,30 @@
void ChassisIntrusionSensor::readGpio()
{
- constexpr size_t readSize = sizeof("0");
- std::string readBuf;
- readBuf.resize(readSize);
- lseek(mFd, 0, SEEK_SET);
- size_t r = ::read(mFd, readBuf.data(), readSize);
- if (r != readSize)
+ mGpioLine.event_read();
+ auto value = mGpioLine.get_value();
+
+ // set string defined in chassis redfish schema
+ std::string newValue = value ? "HardwareIntrusion" : "Normal";
+
+ if (DEBUG)
{
- std::cerr << "Error reading gpio\n";
+ std::cout << "\nGPIO value is " << value << "\n";
+ std::cout << "Intrusion sensor value is " << newValue << "\n";
}
- else
+
+ if (newValue != "unknown" && mValue != newValue)
{
- bool value = std::stoi(readBuf);
- if (mGpioInverted)
- {
- value = !value;
- }
-
- // set string defined in chassis redfish schema
- std::string newValue = value ? "HardwareIntrusion" : "Normal";
-
- if (DEBUG)
- {
- std::cout << "\nGPIO value is " << value << "\n";
- std::cout << "Intrusion sensor value is " << newValue << "\n";
- }
-
- if (newValue != "unknown" && mValue != newValue)
- {
- std::cout << "update value from " << mValue << " to " << newValue
- << "\n";
- updateValue(newValue);
- }
+ std::cout << "update value from " << mValue << " to " << newValue
+ << "\n";
+ updateValue(newValue);
}
}
void ChassisIntrusionSensor::pollSensorStatusByGpio(void)
{
- mInputDev.async_wait(
- boost::asio::ip::tcp::socket::wait_error,
+ mGpioFd.async_wait(
+ boost::asio::posix::stream_descriptor::wait_read,
[this](const boost::system::error_code& ec) {
if (ec == boost::system::errc::bad_file_descriptor)
{
@@ -214,7 +196,8 @@
}
else if (ec)
{
- std::cerr << "Error on GPIO based intrusion sensor socket\n";
+ std::cerr
+ << "Error on GPIO based intrusion sensor wait event\n";
}
else
{
@@ -224,16 +207,44 @@
});
}
-void ChassisIntrusionSensor::initGpioDeviceFile(const int index)
+void ChassisIntrusionSensor::initGpioDeviceFile()
{
- std::string device = gpioPath + std::string("gpio") + std::to_string(index);
- mFd = open((device + "/value").c_str(), O_RDONLY);
- if (mFd < 0)
+ mGpioLine = gpiod::find_line(mPinName);
+ if (!mGpioLine)
{
- std::cerr << "Error opening gpio " << index << "\n";
+ std::cerr << "ChassisIntrusionSensor error finding gpio pin name: "
+ << mPinName << "\n";
return;
}
- mInputDev.assign(boost::asio::ip::tcp::v4(), mFd);
+
+ try
+ {
+
+ mGpioLine.request(
+ {"ChassisIntrusionSensor", gpiod::line_request::EVENT_BOTH_EDGES,
+ mGpioInverted ? gpiod::line_request::FLAG_ACTIVE_LOW : 0});
+
+ // set string defined in chassis redfish schema
+ auto value = mGpioLine.get_value();
+ std::string newValue = value ? "HardwareIntrusion" : "Normal";
+ updateValue(newValue);
+
+ auto gpioLineFd = mGpioLine.event_get_fd();
+ if (gpioLineFd < 0)
+ {
+ std::cerr << "ChassisIntrusionSensor failed to get " << mPinName
+ << " fd\n";
+ return;
+ }
+
+ mGpioFd.assign(gpioLineFd);
+ }
+ catch (std::system_error&)
+ {
+ std::cerr << "ChassisInrtusionSensor error requesting gpio pin name: "
+ << mPinName << "\n";
+ return;
+ }
}
int ChassisIntrusionSensor::setSensorValue(const std::string& req,
@@ -252,8 +263,7 @@
}
void ChassisIntrusionSensor::start(IntrusionSensorType type, int busId,
- int slaveAddr, int gpioIndex,
- bool gpioInverted)
+ int slaveAddr, bool gpioInverted)
{
if (DEBUG)
{
@@ -266,15 +276,15 @@
}
else if (type == IntrusionSensorType::gpio)
{
- std::cerr << "gpioIndex = " << gpioIndex
+ std::cerr << "gpio pinName = " << mPinName
<< ", gpioInverted = " << gpioInverted << "\n";
}
}
if ((type == IntrusionSensorType::pch && busId == mBusId &&
slaveAddr == mSlaveAddr) ||
- (type == IntrusionSensorType::gpio && gpioIndex == mGpioIndex &&
- gpioInverted == mGpioInverted))
+ (type == IntrusionSensorType::gpio && gpioInverted == mGpioInverted &&
+ mInitialized))
{
return;
}
@@ -282,11 +292,10 @@
mType = type;
mBusId = busId;
mSlaveAddr = slaveAddr;
- mGpioIndex = gpioIndex;
mGpioInverted = gpioInverted;
if ((mType == IntrusionSensorType::pch && mBusId > 0 && mSlaveAddr > 0) ||
- (mType == IntrusionSensorType::gpio && mGpioIndex > 0))
+ (mType == IntrusionSensorType::gpio))
{
// initialize first if not initialized before
if (!mInitialized)
@@ -300,7 +309,7 @@
if (mType == IntrusionSensorType::gpio)
{
- initGpioDeviceFile(mGpioIndex);
+ initGpioDeviceFile();
}
mInitialized = true;
@@ -311,8 +320,9 @@
{
pollSensorStatusByPch();
}
- else if (mType == IntrusionSensorType::gpio && mFd > 0)
+ else if (mType == IntrusionSensorType::gpio && mGpioLine)
{
+ std::cerr << "Start polling intrusion sensors\n";
pollSensorStatusByGpio();
}
}
@@ -328,8 +338,11 @@
}
else if (mType == IntrusionSensorType::gpio)
{
- mInputDev.close();
- close(mFd);
+ mGpioFd.close();
+ if (mGpioLine)
+ {
+ mGpioLine.release();
+ }
}
mInitialized = false;
}
@@ -341,8 +354,8 @@
std::shared_ptr<sdbusplus::asio::dbus_interface> iface) :
mIface(iface),
mType(IntrusionSensorType::gpio), mValue("unknown"), mOldValue("unknown"),
- mBusId(-1), mSlaveAddr(-1), mPollTimer(io), mGpioIndex(-1),
- mGpioInverted(false), mInputDev(io)
+ mBusId(-1), mSlaveAddr(-1), mPollTimer(io), mGpioInverted(false),
+ mGpioFd(io)
{
}
@@ -354,7 +367,10 @@
}
else if (mType == IntrusionSensorType::gpio)
{
- mInputDev.close();
- close(mFd);
+ mGpioFd.close();
+ if (mGpioLine)
+ {
+ mGpioLine.release();
+ }
}
}
diff --git a/src/IntrusionSensorMain.cpp b/src/IntrusionSensorMain.cpp
index 96da5f6..b89f628 100644
--- a/src/IntrusionSensorMain.cpp
+++ b/src/IntrusionSensorMain.cpp
@@ -53,7 +53,7 @@
static bool getIntrusionSensorConfig(
std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
- IntrusionSensorType* pType, int* pBusId, int* pSlaveAddr, int* pGpioIndex,
+ IntrusionSensorType* pType, int* pBusId, int* pSlaveAddr,
bool* pGpioInverted)
{
// find matched configuration according to sensor type
@@ -105,30 +105,17 @@
// case to find GPIO info
if (*pType == IntrusionSensorType::gpio)
{
- auto gpioConfig =
- sensorData->find(sensorType + std::string(".GpioIntrusion"));
+ auto findGpioPolarity =
+ baseConfiguration->second.find("GpioPolarity");
- if (gpioConfig == sensorData->end())
+ if (findGpioPolarity == baseConfiguration->second.end())
{
- std::cerr
- << "error finding GpioIntrusion info in configuration \n";
- continue;
- }
-
- auto findGpioIndex = gpioConfig->second.find("Index");
- auto findGpioPolarity = gpioConfig->second.find("Polarity");
-
- if (findGpioIndex == gpioConfig->second.end() ||
- findGpioPolarity == gpioConfig->second.end())
- {
- std::cerr << "error finding gpio info in configuration \n";
+ std::cerr << "error finding gpio polarity in configuration \n";
continue;
}
try
{
- *pGpioIndex = sdbusplus::message::variant_ns::get<uint64_t>(
- findGpioIndex->second);
*pGpioInverted =
(sdbusplus::message::variant_ns::get<std::string>(
findGpioPolarity->second) == "Low");
@@ -141,9 +128,9 @@
if (DEBUG)
{
- std::cout << "find matched GPIO index " << *pGpioIndex
- << ", polarity inverted flag is " << *pGpioInverted
- << "\n";
+ std::cout << "find chassis intrusion sensor polarity inverted "
+ "flag is "
+ << *pGpioInverted << "\n";
}
return true;
@@ -187,7 +174,6 @@
"sensor. \n";
*pBusId = -1;
*pSlaveAddr = -1;
- *pGpioIndex = -1;
return false;
}
@@ -457,7 +443,8 @@
int main()
{
- int busId = -1, slaveAddr = -1, gpioIndex = -1;
+ int busId = -1;
+ int slaveAddr = -1;
bool gpioInverted = false;
IntrusionSensorType type = IntrusionSensorType::gpio;
@@ -477,10 +464,9 @@
ChassisIntrusionSensor chassisIntrusionSensor(io, ifaceChassis);
if (getIntrusionSensorConfig(systemBus, &type, &busId, &slaveAddr,
- &gpioIndex, &gpioInverted))
+ &gpioInverted))
{
- chassisIntrusionSensor.start(type, busId, slaveAddr, gpioIndex,
- gpioInverted);
+ chassisIntrusionSensor.start(type, busId, slaveAddr, gpioInverted);
}
// callback to handle configuration change
@@ -494,9 +480,9 @@
std::cout << "rescan due to configuration change \n";
if (getIntrusionSensorConfig(systemBus, &type, &busId, &slaveAddr,
- &gpioIndex, &gpioInverted))
+ &gpioInverted))
{
- chassisIntrusionSensor.start(type, busId, slaveAddr, gpioIndex,
+ chassisIntrusionSensor.start(type, busId, slaveAddr,
gpioInverted);
}
};