summaryrefslogtreecommitdiff
path: root/gpiodaemon
diff options
context:
space:
mode:
authorWang, Kuiying <kuiying.wang@intel.com>2019-01-10 07:04:02 +0300
committerGerrit Code Review <gerrit@localhost>2019-01-10 07:04:02 +0300
commit02e39dd2b8f8ebc846417f4950d122f3b6da8f78 (patch)
tree1bed923380f273d8d450592230d5126631220da2 /gpiodaemon
parentf145b95e4bf57a60413480214b879edd57f8497a (diff)
parentbcbdf1ee4b863f72b83ecadf21399078e317facc (diff)
downloadprovingground-02e39dd2b8f8ebc846417f4950d122f3b6da8f78.tar.xz
Merge "Monitor gpio value changes"
Diffstat (limited to 'gpiodaemon')
-rw-r--r--gpiodaemon/include/gpiodaemon.hpp78
-rw-r--r--gpiodaemon/src/gpiodaemon.cpp199
2 files changed, 219 insertions, 58 deletions
diff --git a/gpiodaemon/include/gpiodaemon.hpp b/gpiodaemon/include/gpiodaemon.hpp
index 07c72aa..424bf99 100644
--- a/gpiodaemon/include/gpiodaemon.hpp
+++ b/gpiodaemon/include/gpiodaemon.hpp
@@ -25,6 +25,7 @@ class GpioEn
std::string name;
uint16_t number;
bool enabled;
+ bool value;
public:
GpioEn(const std::string& name_, uint16_t number_, bool enabled_) :
@@ -46,20 +47,87 @@ class GpioEn
{
enabled = value;
}
+ bool getValue() const
+ {
+ return value;
+ }
+ void setvalue(bool val)
+ {
+ value = val;
+ }
+};
+
+class GpioState
+{
+ bool state = true;
+ const bool inverted;
+ const std::string gpioName;
+ int fdValue;
+
+ boost::asio::ip::tcp::socket inputDev;
+ std::shared_ptr<sdbusplus::asio::dbus_interface> iface;
+
+ void monitor(void);
+ void readValue(void);
+
+ public:
+ GpioState(const std::string gpioName, const uint16_t gpioNumber,
+ const bool inverted, boost::asio::io_service& io,
+ std::shared_ptr<sdbusplus::asio::dbus_interface>& iface);
+ GpioState(GpioState&&) = default;
+ GpioState& operator=(GpioState&&) = default;
+ ~GpioState();
+
+ std::string getName() const
+ {
+ return gpioName;
+ }
+ bool getValue(void) const
+ {
+ return state;
+ }
};
class GpioManager
{
- std::vector<GpioEn> gpioEnableList;
+ boost::asio::io_service& io;
sdbusplus::asio::object_server& server;
std::shared_ptr<sdbusplus::asio::connection> conn;
std::shared_ptr<sdbusplus::asio::dbus_interface> iface;
- std::vector<std::string> paths;
- GpioEn* findGpioObj(const std::string& gpioName);
+ std::vector<GpioEn> gpioEnableList;
+ std::vector<std::unique_ptr<GpioState>> gpioMonitorList;
+
+ GpioEn* findGpioObj(const std::string& gpioName)
+ {
+ auto el = std::find_if(gpioEnableList.begin(), gpioEnableList.end(),
+ [&gpioName](const GpioEn& obj) {
+ return obj.getName() == gpioName;
+ });
+ if (el != gpioEnableList.end())
+ {
+ return &(*el);
+ }
+ return nullptr;
+ }
+
+ bool getGpioStateValue(const std::string& gpioName, bool& value)
+ {
+ for (const auto& gpio : gpioMonitorList)
+ {
+ if (gpio->getName() == gpioName)
+ {
+ value = gpio->getValue();
+ return true;
+ }
+ }
+ return false;
+ }
public:
- GpioManager(sdbusplus::asio::object_server& srv,
+ GpioManager(boost::asio::io_service& io,
+ sdbusplus::asio::object_server& srv,
std::shared_ptr<sdbusplus::asio::connection>& conn);
- void addObject(std::string path);
+
+ void addObject(const std::string& path);
};
diff --git a/gpiodaemon/src/gpiodaemon.cpp b/gpiodaemon/src/gpiodaemon.cpp
index 633d782..2ef9c3a 100644
--- a/gpiodaemon/src/gpiodaemon.cpp
+++ b/gpiodaemon/src/gpiodaemon.cpp
@@ -28,6 +28,7 @@ static constexpr const char* gpioConfigInterface =
"xyz.openbmc_project.Configuration.Gpio";
static constexpr const char* gpioInterface = "xyz.openbmc_project.Control.Gpio";
static constexpr const char* gpioPath = "/xyz/openbmc_project/control/gpio/";
+static constexpr const char* sysGpioPath = "/sys/class/gpio/gpio";
static constexpr const char* propInterface = "org.freedesktop.DBus.Properties";
static constexpr const char* objPath = "/xyz/openbmc_project/object_mapper";
@@ -40,13 +41,13 @@ using BasicVariantType =
sdbusplus::message::variant<std::string, int64_t, uint64_t, double, int32_t,
uint32_t, int16_t, uint16_t, uint8_t, bool>;
-void GpioManager::addObject(std::string path)
+void GpioManager::addObject(const std::string& path)
{
conn->async_method_call(
[this,
- &path](boost::system::error_code ec,
- const boost::container::flat_map<std::string, BasicVariantType>&
- result) {
+ path](boost::system::error_code ec,
+ const boost::container::flat_map<std::string, BasicVariantType>&
+ result) {
if (ec)
{
phosphor::logging::log<phosphor::logging::level::INFO>(
@@ -100,10 +101,10 @@ void GpioManager::addObject(std::string path)
iface->register_property(
"Enabled", true,
[this, gpioName](const bool& req, bool& propertyValue) {
- auto it = findGpioObj(gpioName);
- if (it != nullptr)
+ GpioEn* dbusGpio = findGpioObj(gpioName);
+ if (dbusGpio)
{
- it->setEnabled(req);
+ dbusGpio->setEnabled(req);
propertyValue = req;
return 1;
}
@@ -120,16 +121,16 @@ void GpioManager::addObject(std::string path)
// Override set
[this, gpioName, inverted](const bool& req,
bool& propertyValue) {
- auto it = findGpioObj(gpioName);
+ GpioEn* dbusGpio = findGpioObj(gpioName);
- if (it != nullptr)
+ if (dbusGpio)
{
// If Gpio enabled property is set as true then
// reject set request
- if (it->getEnabled())
+ if (dbusGpio->getEnabled())
{
Gpio gpio =
- Gpio(std::to_string(it->getNumber()));
+ Gpio(std::to_string(dbusGpio->getNumber()));
bool setVal = req;
if (inverted)
{
@@ -137,12 +138,29 @@ void GpioManager::addObject(std::string path)
}
gpio.setValue(static_cast<GpioValue>(setVal));
- propertyValue = req;
+ propertyValue = setVal;
return 1;
}
return 0;
}
return 0;
+ },
+ // Override get
+ [this, gpioName](const bool& propertyValue) {
+ bool value;
+ if (getGpioStateValue(gpioName, value))
+ {
+ return value;
+ }
+ else // Gpio with direction "out" are not monitored.
+ // Return last know state.
+ {
+ GpioEn* dbuGpio = findGpioObj(gpioName);
+ if (dbuGpio)
+ {
+ return dbuGpio->getValue();
+ }
+ }
});
iface->register_property(
@@ -150,16 +168,16 @@ void GpioManager::addObject(std::string path)
// Override set
[this, gpioName](const std::string& req,
std::string& propertyValue) {
- auto it = findGpioObj(gpioName);
+ GpioEn* dbusGpio = findGpioObj(gpioName);
- if (it != nullptr)
+ if (dbusGpio)
{
// If Gpio enabled property is set as true than
// reject request
- if (it->getEnabled())
+ if (dbusGpio->getEnabled())
{
Gpio gpio =
- Gpio(std::to_string(it->getNumber()));
+ Gpio(std::to_string(dbusGpio->getNumber()));
gpio.setDirection(req);
propertyValue = req;
@@ -168,77 +186,152 @@ void GpioManager::addObject(std::string path)
return 0;
}
return 0;
+ },
+ // Override get
+ [this, index](const std::string& propertyDirection) {
+ // Read present gpio data from /sys/class/gpio/...
+ Gpio gpio = Gpio(std::to_string(index));
+ return gpio.getDirection();
});
iface->initialize();
+
+ // Monitor gpio value changes
+ gpioMonitorList.push_back(std::make_unique<GpioState>(
+ gpioName, index, inverted, io, iface));
}
},
entityMgrService, path, propInterface, "GetAll", gpioConfigInterface);
}
-GpioManager::GpioManager(sdbusplus::asio::object_server& srv_,
+GpioManager::GpioManager(boost::asio::io_service& io_,
+ sdbusplus::asio::object_server& srv_,
std::shared_ptr<sdbusplus::asio::connection>& conn_) :
- server(srv_),
- conn(conn_)
+ io(io_),
+ server(srv_), conn(conn_)
{
using GetSubTreeType = std::vector<std::pair<
std::string,
std::vector<std::pair<std::string, std::vector<std::string>>>>>;
+ constexpr int32_t scanDepth = 3;
- auto mesg =
- conn->new_method_call(objService, objPath, objInterface, "GetSubTree");
-
- static const auto depth = 3;
- mesg.append("/xyz/openbmc_project/inventory/system", depth,
- std::vector<std::string>());
+ conn->async_method_call(
+ [this](boost::system::error_code ec, GetSubTreeType& subtree) {
+ if (ec)
+ {
+ phosphor::logging::log<phosphor::logging::level::INFO>(
+ "ERROR with async_method_call to ObjectMapper");
+ return;
+ }
- conn->async_send(mesg, [this](boost::system::error_code ec,
- sdbusplus::message::message& ret) {
- if (ec)
- {
- phosphor::logging::log<phosphor::logging::level::INFO>(
- "ERROR with async_send");
- return;
- }
- GetSubTreeType subtree;
- ret.read(subtree);
-
- for (const auto& i : subtree)
- {
- for (const auto& j : i.second)
+ for (const auto& objectPath : subtree)
{
- for (const auto& k : j.second)
+ for (const auto& objectInterfaces : objectPath.second)
{
- if (gpioConfigInterface == k)
+ for (const auto& interface : objectInterfaces.second)
{
- addObject(i.first);
+ if (gpioConfigInterface == interface)
+ {
+ addObject(objectPath.first);
+ }
}
}
}
- }
- });
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+ "/xyz/openbmc_project/inventory/system", scanDepth,
+ std::vector<std::string>());
}
-GpioEn* GpioManager::findGpioObj(const std::string& gpioName)
+GpioState::GpioState(const std::string gpioName_, const uint16_t gpioNumber,
+ const bool inverted_, boost::asio::io_service& io_,
+ std::shared_ptr<sdbusplus::asio::dbus_interface>& iface_) :
+ gpioName(gpioName_),
+ inverted(inverted_), inputDev(io_), iface(iface_)
{
- auto it = std::find_if(
- gpioEnableList.begin(), gpioEnableList.end(),
- [&gpioName](const GpioEn& obj) { return obj.getName() == gpioName; });
- if (it != gpioEnableList.end())
+ // todo: implement gpio device character access
+ std::string device = sysGpioPath + std::to_string(gpioNumber);
+
+ fdValue = open((device + "/value").c_str(), O_RDONLY);
+ if (fdValue < 0)
+ {
+ phosphor::logging::log<phosphor::logging::level::INFO>(
+ ("GpioState: Error opening " + device).c_str());
+ return;
+ }
+
+ std::ofstream deviceFileEdge(device + "/edge");
+ if (!deviceFileEdge.good())
{
- return &(*it);
+ phosphor::logging::log<phosphor::logging::level::INFO>(
+ ("GpioState:Error setting edge for" + device).c_str());
+ return;
}
- return nullptr;
+ deviceFileEdge << "both"; // Will success only for gpio.direction == "in"
+ deviceFileEdge.close();
+
+ inputDev.assign(boost::asio::ip::tcp::v4(), fdValue);
+ monitor();
+ readValue();
+}
+
+GpioState::~GpioState()
+{
+ inputDev.close();
+ close(fdValue);
+}
+
+void GpioState::monitor(void)
+{
+ inputDev.async_wait(
+ boost::asio::ip::tcp::socket::wait_error,
+ [this](const boost::system::error_code& ec) {
+ if (ec == boost::system::errc::bad_file_descriptor)
+ {
+ return; // we're being destroyed
+ }
+ else if (ec)
+ {
+ phosphor::logging::log<phosphor::logging::level::INFO>(
+ ("GpioState:monitor: Error on presence sensor socket"));
+ }
+ else
+ {
+ readValue();
+ }
+ monitor();
+ });
+}
+
+void GpioState::readValue(void)
+{
+ constexpr size_t readSize = sizeof("0");
+
+ std::string readBuf;
+ readBuf.resize(readSize);
+ lseek(fdValue, 0, SEEK_SET);
+
+ size_t r = ::read(fdValue, readBuf.data(), readSize);
+ bool value = std::stoi(readBuf);
+ if (inverted)
+ {
+ value = !value;
+ }
+ state = value;
+
+ // Broadcast value changed property signal
+ iface->signal_property("Value");
}
int main()
{
boost::asio::io_service io;
auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
-
systemBus->request_name(gpioService);
sdbusplus::asio::object_server server(systemBus);
- GpioManager gpioMgr(server, systemBus);
+ GpioManager gpioMgr(io, server, systemBus);
static auto match = std::make_unique<sdbusplus::bus::match::match>(
static_cast<sdbusplus::bus::bus&>(*systemBus),