From ce822444460a6aef6538c36b9c74023c33e2fcae Mon Sep 17 00:00:00 2001 From: Brandon Wyman Date: Mon, 10 Apr 2017 17:48:02 -0500 Subject: Implement changes to read GPIO device for cooling type. Change-Id: If40a54510fb05d67ee0bfdf24026c1d7470897ca Signed-off-by: Brandon Wyman --- configure.ac | 4 ++-- cooling-type/Makefile.am | 8 ++++--- cooling-type/argument.cpp | 22 +++++++++++------ cooling-type/cooling_type.cpp | 54 +++++++++++++++++++++++++++++------------ cooling-type/cooling_type.hpp | 27 ++++++++++++++------- cooling-type/main.cpp | 56 ++++++++++++++++++++++--------------------- utility.hpp | 17 +++++++++++++ 7 files changed, 126 insertions(+), 62 deletions(-) diff --git a/configure.ac b/configure.ac index c3e18bb..e698150 100644 --- a/configure.ac +++ b/configure.ac @@ -62,7 +62,7 @@ AC_ARG_ENABLE([monitor], AM_CONDITIONAL([WANT_PRESENCE], [test "x$enable_presence" != "xno"]) AM_CONDITIONAL([WANT_CONTROL], [test "x$enable_control" != "xno"]) -AM_CONDITIONAL([WANT_COOLING_TYPE], [test "x$enable_cooling-type" != "xno"]) +AM_CONDITIONAL([WANT_COOLING_TYPE], [test "x$enable_cooling_type" != "xno"]) AM_CONDITIONAL([WANT_MONITOR], [test "x$enable_monitor" != "xno"]) # Package specific checks. @@ -111,7 +111,7 @@ AS_IF([test "x$enable_control" != "xno"], [ AC_CONFIG_FILES([control/Makefile]) ]) -AS_IF([test "x$enable_cooling-type" != "xno"], [ +AS_IF([test "x$enable_cooling_type" != "xno"], [ PKG_CHECK_MODULES([LIBEVDEV], [libevdev], , [AC_MSG_ERROR([The libevdev package is required])]) AC_CONFIG_FILES([cooling-type/Makefile]) diff --git a/cooling-type/Makefile.am b/cooling-type/Makefile.am index 8b41812..b18b2d6 100644 --- a/cooling-type/Makefile.am +++ b/cooling-type/Makefile.am @@ -11,11 +11,13 @@ phosphor_cooling_type_SOURCES = \ phosphor_cooling_type_CXXFLAGS = \ $(SDBUSPLUS_CFLAGS) \ - $(PHOSPHOR_LOGGING_CFLAGS) + $(PHOSPHOR_LOGGING_CFLAGS) \ + $(LIBEVDEV_CFLAGS) phosphor_cooling_type_LDADD = \ - $(top_builddir)/libfan.la \ + ${top_builddir}/libfan.la \ $(SDBUSPLUS_LIBS) \ - $(PHOSPHOR_LOGGING_LIBS) + $(PHOSPHOR_LOGGING_LIBS) \ + $(LIBEVDEV_LIBS) # vim: tabstop=8 noexpandtab diff --git a/cooling-type/argument.cpp b/cooling-type/argument.cpp index da1e5a3..f0a78c2 100644 --- a/cooling-type/argument.cpp +++ b/cooling-type/argument.cpp @@ -70,26 +70,34 @@ void ArgumentParser::usage(char** argv) std::cerr << "Usage: " << argv[0] << " [options]\n"; std::cerr << "Options:\n"; std::cerr << " --help print this menu\n"; - std::cerr << " --air Indicate air cooled is set\n"; - std::cerr << " --water Indicate water cooled is set\n"; - std::cerr << " --gpio= GPIO pin to read\n"; + std::cerr << " --air Force 'AirCooled' property to be set" + " to true.\n"; + std::cerr << " --water Force 'WaterCooled' property to be " + "set to true.\n"; + std::cerr << " --dev= Device to read for GPIO pin state to" + " determine 'WaterCooled' (true) and 'AirCooled' (false)\n"; + std::cerr << " --event= Keycode for pin to read\n"; std::cerr << - " --path= Object path under inventory to have " - "CoolingType updated\n"; + " --path= *Required* object path under inventory " + "to have CoolingType updated\n"; + std::cerr << "\nThe --air / --water options may be given in addtion to " + "--gpio, in which case both their setting and the GPIO will take " + "effect.\n"; std::cerr << std::flush; } const option ArgumentParser::options[] = { { "path", required_argument, NULL, 'p' }, - { "gpio", required_argument, NULL, 'g' }, + { "dev", required_argument, NULL, 'd' }, + { "event", required_argument, NULL, 'e' }, { "air", no_argument, NULL, 'a' }, { "water", no_argument, NULL, 'w' }, { "help", no_argument, NULL, 'h' }, { 0, 0, 0, 0}, }; -const char* ArgumentParser::optionstr = "p:g:aw?h"; +const char* ArgumentParser::optionstr = "p:d:e:aw?h"; const std::string ArgumentParser::empty_string = ""; diff --git a/cooling-type/cooling_type.cpp b/cooling-type/cooling_type.cpp index 1c36daf..eb4a449 100644 --- a/cooling-type/cooling_type.cpp +++ b/cooling-type/cooling_type.cpp @@ -1,7 +1,8 @@ -#include #include +#include #include #include +#include #include "utility.hpp" #include "cooling_type.hpp" @@ -12,6 +13,23 @@ namespace cooling namespace type { +std::unique_ptr evdevOpen(int fd) +{ + libevdev* gpioDev = nullptr; + + auto rc = libevdev_new_from_fd(fd, &gpioDev); + if (!rc) + { + return decltype(evdevOpen(0))(gpioDev); + } + + //TODO - Create error log for failure. openbmc/openbmc#1542 + throw std::runtime_error("Failed to get libevdev from file descriptor" + " rc = " + std::to_string(rc)); + + return decltype(evdevOpen(0))(nullptr); +} + void CoolingType::setAirCooled() { airCooled = true; @@ -22,26 +40,33 @@ void CoolingType::setWaterCooled() waterCooled = true; } -void CoolingType::setupGpio(const std::string& gpioPath) +void CoolingType::readGpio(const std::string& gpioPath, unsigned int keycode) { using namespace phosphor::logging; - gpioFd = open(gpioPath.c_str(), O_RDONLY); - if (gpioFd.is_open()) + gpioFd.open(gpioPath.c_str(), O_RDONLY); + + auto gpioDev = evdevOpen(gpioFd()); + + auto value = static_cast(0); + auto fetch_rc = libevdev_fetch_event_value(gpioDev.get(), EV_KEY, + keycode, &value); + if (0 == fetch_rc) + { + //TODO - Create error log for failure. openbmc/openbmc#1542 + throw std::runtime_error( + "Device does not support event type=EV_KEY and code=" + + std::to_string(keycode)); + } + + // TODO openbmc/phosphor-fan-presence#6 + if (value > 0) { - auto rc = 0;//libevdev_new_from_fd(gpiofd, &gpioDev);//FIXME - if (rc < 0) - { - throw std::runtime_error("Failed to get libevdev from " + - gpioPath + " rc = " + - std::to_string(rc)); - } - - //TODO - more to go here? + setWaterCooled(); } else { - throw std::runtime_error("Failed to open GPIO file device"); + setAirCooled(); } } @@ -88,5 +113,4 @@ void CoolingType::updateInventory(const std::string& objpath) } } } - // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/cooling-type/cooling_type.hpp b/cooling-type/cooling_type.hpp index 8775a42..aa02bfa 100644 --- a/cooling-type/cooling_type.hpp +++ b/cooling-type/cooling_type.hpp @@ -1,5 +1,6 @@ #pragma once #include "utility.hpp" +#include namespace phosphor { @@ -11,6 +12,14 @@ namespace type constexpr auto INVENTORY_PATH = "/xyz/openbmc_project/inventory"; constexpr auto INVENTORY_INTF = "xyz.openbmc_project.Inventory.Manager"; +struct FreeEvDev +{ + void operator()(struct libevdev* device) const + { + libevdev_free(device); + } +}; + class CoolingType { using Property = std::string; @@ -39,6 +48,7 @@ class CoolingType */ CoolingType(sdbusplus::bus::bus& bus) : bus(bus) { + //TODO: Issue openbmc/openbmc#1531 - means to default properties. } /** @@ -52,15 +62,16 @@ class CoolingType /** * @brief Updates the inventory properties for CoolingType. * - * @param[in] path - D-Bus path + * @param[in] path - Path to object to update */ - void updateInventory(const std::string&); + void updateInventory(const std::string& path); /** - * @brief Setup the GPIO device for reading cooling type. + * @brief Setup and read the GPIO device for reading cooling type. * - * @param[in] - Path to object to update + * @param[in] path - Path to the GPIO device file to read + * @param[in] pin - Event/key code to read (pin) */ - void setupGpio(const std::string&); + void readGpio(const std::string& path, unsigned int pin); private: /** @brief Connection for sdbusplus bus */ @@ -73,11 +84,11 @@ class CoolingType /** * @brief Construct the inventory object map for CoolingType. * - * @param[in] - Path to object to update + * @param[in] objpath - Path to object to update * * @return The inventory object map to update inventory - */ - ObjectMap getObjectMap(const std::string&); + */ + ObjectMap getObjectMap(const std::string& objpath); }; diff --git a/cooling-type/main.cpp b/cooling-type/main.cpp index 91934ea..caa4e88 100644 --- a/cooling-type/main.cpp +++ b/cooling-type/main.cpp @@ -8,14 +8,6 @@ using namespace phosphor::cooling::type; using namespace phosphor::logging; -// Utility function to find the device string for a given pin name. -std::string findGpio(std::string pinName) -{ - std::string path = "/dev/null"; - //TODO - return path; -} - int main(int argc, char* argv[]) { auto rc = -1; @@ -37,36 +29,46 @@ int main(int argc, char* argv[]) auto bus = sdbusplus::bus::new_default(); CoolingType coolingType(bus); - auto gpiopin = (options)["gpio"]; - if (gpiopin != ArgumentParser::empty_string) + try { - try + auto air = (options)["air"]; + if (air != ArgumentParser::empty_string) { - auto gpiopath = findGpio(gpiopin); - coolingType.setupGpio(gpiopath); + coolingType.setAirCooled(); } - catch (std::exception& err) + + auto water = (options)["water"]; + if (water != ArgumentParser::empty_string) { - rc = -1; - log(err.what()); + coolingType.setWaterCooled(); } - } - auto air = (options)["air"]; - if (air != ArgumentParser::empty_string) - { - coolingType.setAirCooled(); + auto gpiopath = (options)["dev"]; + if (gpiopath != ArgumentParser::empty_string) + { + auto keycode = (options)["event"]; + if (keycode != ArgumentParser::empty_string) + { + auto gpiocode = std::stoul(keycode); + coolingType.readGpio(gpiopath, gpiocode); + } + else + { + log("--event= argument required\n"); + exit(-1); + } + } + + coolingType.updateInventory(objpath); + rc = 0; } - auto water = (options)["water"]; - if (water != ArgumentParser::empty_string) + catch (std::exception& err) { - coolingType.setWaterCooled(); + rc = -1; + log(err.what()); } - coolingType.updateInventory(objpath); - - rc = 0; } return rc; diff --git a/utility.hpp b/utility.hpp index 05fe60c..880545a 100644 --- a/utility.hpp +++ b/utility.hpp @@ -2,6 +2,8 @@ #include #include +#include + namespace phosphor { @@ -31,6 +33,21 @@ class FileDescriptor } } + int operator()() + { + return fd; + } + + void open(const std::string& pathname, int flags) + { + fd = ::open(pathname.c_str(), flags); + if (-1 == fd) + { + throw std::runtime_error( + "Failed to open file device: " + pathname); + } + } + bool is_open() { return fd != -1; -- cgit v1.2.1