summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Spinler <spinler@us.ibm.com>2017-05-25 10:23:05 -0500
committerMatt Spinler <spinler@us.ibm.com>2017-05-30 15:25:31 -0500
commit36df1979f5c11d4e4dbe144b63f42390b6088f76 (patch)
tree42e97a07668e3f3ed7a4cc460e4888dd1e3d15bf
parent936a504319e01642fc5803c00ff4aa5baeafacef (diff)
downloadphosphor-gpio-monitor-36df1979f5c11d4e4dbe144b63f42390b6088f76.tar.gz
phosphor-gpio-monitor-36df1979f5c11d4e4dbe144b63f42390b6088f76.zip
Add GPIO class
This class is used for accessing a GPIO via the /dev/gpiochipX interface. It requests a GPIO line handle from the GPIO device to do the actual operation on. The GPIO number to use, for AST chips at least, is the actual GPIO number, such as GPIOA0 = 0 and GPIOA7 = 7. The class currently only supports writes. Change-Id: I1c2ae38c23c5db502d5f14bcf9aa2e35094f1e9b Signed-off-by: Matt Spinler <spinler@us.ibm.com>
-rw-r--r--configure.ac7
-rw-r--r--file.hpp12
-rw-r--r--gpio-util/Makefile.am7
-rw-r--r--gpio-util/gpio.cpp98
-rw-r--r--gpio-util/gpio.hpp108
5 files changed, 231 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index ae95205..1a2bb98 100644
--- a/configure.ac
+++ b/configure.ac
@@ -24,6 +24,13 @@ PKG_CHECK_MODULES([SDBUSPLUS], [sdbusplus],, [AC_MSG_ERROR([Could not find sdbus
PKG_CHECK_MODULES([PHOSPHOR_DBUS_INTERFACES], [phosphor-dbus-interfaces],, [AC_MSG_ERROR([Could not find phosphor-dbus-interfaces...openbmc/phosphor-dbus-interfaces package required])])
PKG_CHECK_MODULES([LIBEVDEV], [libevdev],, [AC_MSG_ERROR([Could not find libevdev...libevdev package required])])
+# Download gpio.h from github if necessary.
+AC_CHECK_HEADER(linux/gpio.h,[HAVE_LINUX_GPIO_H=""],[HAVE_LINUX_GPIO_H="-I linux/gpio.h"])
+AS_IF([test "$HAVE_LINUX_GPIO_H" != ""],
+ AC_MSG_WARN([Could not find linux/gpio.h: Attempting to download locally for building from https://raw.githubusercontent.com/torvalds/linux/master/include/uapi/linux/gpio.h])
+ AC_SUBST([BT_BMC_DL],[`mkdir -p linux;wget https://raw.githubusercontent.com/torvalds/linux/master/include/uapi/linux/gpio.h -O linux/gpio.h`])
+)
+
# Check/set gtest specific functions.
AX_PTHREAD([GTEST_CPPFLAGS="-DGTEST_HAS_PTHREAD=1"],[GTEST_CPPFLAGS="-DGTEST_HAS_PTHREAD=0"])
AC_SUBST(GTEST_CPPFLAGS)
diff --git a/file.hpp b/file.hpp
index 9ba4cbb..ee8fd4b 100644
--- a/file.hpp
+++ b/file.hpp
@@ -15,7 +15,7 @@ class FileDescriptor
int fd = -1;
public:
- FileDescriptor() = delete;
+ FileDescriptor() = default;
FileDescriptor(const FileDescriptor&) = delete;
FileDescriptor& operator=(const FileDescriptor&) = delete;
FileDescriptor(FileDescriptor&&) = delete;
@@ -42,6 +42,16 @@ class FileDescriptor
{
return fd;
}
+
+ operator bool() const
+ {
+ return fd != -1;
+ }
+
+ void set(int descriptor)
+ {
+ fd = descriptor;
+ }
};
} // namespace gpio
diff --git a/gpio-util/Makefile.am b/gpio-util/Makefile.am
index ea8c763..9bdc42d 100644
--- a/gpio-util/Makefile.am
+++ b/gpio-util/Makefile.am
@@ -5,4 +5,11 @@ sbin_PROGRAMS = \
phosphor-gpio-util
phosphor_gpio_util_SOURCES = \
+ gpio.cpp \
main.cpp
+
+phosphor_gpio_util_LDADD = \
+ $(PHOSPHOR_LOGGING_LIBS)
+
+phosphor_gpio_util_CXXFLAGS = \
+ $(PHOSPHOR_LOGGING_CFLAGS)
diff --git a/gpio-util/gpio.cpp b/gpio-util/gpio.cpp
new file mode 100644
index 0000000..d5c2ce4
--- /dev/null
+++ b/gpio-util/gpio.cpp
@@ -0,0 +1,98 @@
+/**
+ * Copyright © 2017 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <fcntl.h>
+#include <phosphor-logging/log.hpp>
+#include <sys/ioctl.h>
+#include "gpio.hpp"
+
+namespace phosphor
+{
+namespace gpio
+{
+
+using namespace phosphor::logging;
+
+void GPIO::set(Value value)
+{
+ assert(direction == Direction::output);
+
+ requestLine(value);
+
+ gpiohandle_data data{};
+ data.values[0] = static_cast<gpioValue_t>(value);
+
+ auto rc = ioctl(lineFD(), GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data);
+ if (rc == -1)
+ {
+ auto e = errno;
+ log<level::ERR>("Failed SET_LINE_VALUES ioctl",
+ entry("ERRNO=%d", e));
+ throw std::runtime_error("Failed SET_LINE_VALUES ioctl");
+ }
+}
+
+
+void GPIO::requestLine(Value defaultValue)
+{
+ //Only need to do this once
+ if (lineFD)
+ {
+ return;
+ }
+
+ FileDescriptor fd{open(device.c_str(), 0)};
+ if (fd() == -1)
+ {
+ auto e = errno;
+ log<level::ERR>("Failed opening GPIO device",
+ entry("DEVICE=%s", device),
+ entry("ERRNO=%d", e));
+ throw std::runtime_error("Failed opening GPIO device");
+ }
+
+ //Make an ioctl call to request the GPIO line, which will
+ //return the descriptor to use to access it.
+ gpiohandle_request request{};
+ strncpy(request.consumer_label,
+ "phosphor-gpio-util",
+ sizeof(request.consumer_label));
+
+ request.flags = (direction == Direction::output) ?
+ GPIOHANDLE_REQUEST_OUTPUT : GPIOHANDLE_REQUEST_INPUT;
+
+ request.lineoffsets[0] = gpio;
+ request.lines = 1;
+
+ if (direction == Direction::output)
+ {
+ request.default_values[0] = static_cast<gpioValue_t>(defaultValue);
+ }
+
+ auto rc = ioctl(fd(), GPIO_GET_LINEHANDLE_IOCTL, &request);
+ if (rc == -1)
+ {
+ auto e = errno;
+ log<level::ERR>("Failed GET_LINEHANDLE ioctl",
+ entry("GPIO=%d", gpio),
+ entry("ERRNO=%d", e));
+ throw std::runtime_error("Failed GET_LINEHANDLE ioctl");
+ }
+
+ lineFD.set(request.fd);
+}
+
+}
+}
diff --git a/gpio-util/gpio.hpp b/gpio-util/gpio.hpp
new file mode 100644
index 0000000..ba8cce3
--- /dev/null
+++ b/gpio-util/gpio.hpp
@@ -0,0 +1,108 @@
+#pragma once
+
+#include <linux/gpio.h>
+#include "file.hpp"
+
+namespace phosphor
+{
+namespace gpio
+{
+
+ typedef std::remove_reference<decltype(
+ gpiohandle_request::lineoffsets[0])>::type gpioNum_t;
+
+ typedef std::remove_reference<decltype(
+ gpiohandle_data::values[0])>::type gpioValue_t;
+
+/**
+ * Represents a GPIO.
+ *
+ * Operations are setting low or high.
+ *
+ * Read support may be added in the future.
+ */
+class GPIO
+{
+ public:
+
+ /**
+ * If the GPIO is an input or output
+ */
+ enum class Direction
+ {
+ input,
+ output
+ };
+
+ /**
+ * The possible values - low or high
+ */
+ enum class Value
+ {
+ low,
+ high
+ };
+
+ GPIO() = delete;
+ GPIO(const GPIO&) = delete;
+ GPIO(GPIO&&) = default;
+ GPIO& operator=(const GPIO&) = delete;
+ GPIO& operator=(GPIO&&) = default;
+ ~GPIO() = default;
+
+ /**
+ * Constructor
+ *
+ * @param[in] device - the GPIO device file
+ * @param[in] gpio - the GPIO number
+ * @param[in] direction - the GPIO direction
+ */
+ GPIO(const std::string& device,
+ gpioNum_t gpio,
+ Direction direction) :
+ device(device),
+ gpio(gpio),
+ direction(direction)
+ {
+ }
+
+ /**
+ * Sets the GPIO value
+ *
+ * Requests the GPIO line if it hasn't been done already.
+ */
+ void set(Value value);
+
+ private:
+
+ /**
+ * Requests a GPIO line from the GPIO device
+ *
+ * @param[in] defaultValue - The default value, required for
+ * output GPIOs only.
+ */
+ void requestLine(Value defaultValue = Value::high);
+
+ /**
+ * The GPIO device name, like /dev/gpiochip0
+ */
+ const std::string device;
+
+ /**
+ * The GPIO number
+ */
+ const gpioNum_t gpio;
+
+ /**
+ * The GPIO direction
+ */
+ const Direction direction;
+
+ /**
+ * File descriptor for the GPIO line
+ */
+ FileDescriptor lineFD;
+};
+
+}
+}
OpenPOWER on IntegriCloud