pseq: Create GPIO class hierarchy
Create GPIO class hierarchy within the phosphor-power-sequencer
application.
The GPIO abstract base class declares virtual methods for requesting,
reading, writing, and releasing a GPIO.
The BMCGPIO subclass provides a real implementation using the libgpiod
API.
The MockGPIO subclass provides a mock implementation for automated
testing.
Tested:
* Verified GPIO could be read
* Verified GPIO could be written
* Verified error paths
* Verified MockGPIO could be used in an automated test
Change-Id: Ie5808988c5d743c44735f5bc4c09cd15b397518b
Signed-off-by: Shawn McCarney <shawnmm@us.ibm.com>
diff --git a/phosphor-power-sequencer/src/gpio.hpp b/phosphor-power-sequencer/src/gpio.hpp
new file mode 100644
index 0000000..d7ebf83
--- /dev/null
+++ b/phosphor-power-sequencer/src/gpio.hpp
@@ -0,0 +1,150 @@
+/**
+ * Copyright © 2025 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.
+ */
+#pragma once
+
+#include <gpiod.hpp>
+
+#include <string>
+
+namespace phosphor::power::sequencer
+{
+
+/**
+ * @class GPIO
+ *
+ * Abstract base class for a General-Purpose Input/Output pin.
+ */
+class GPIO
+{
+ public:
+ GPIO() = default;
+ GPIO(const GPIO&) = delete;
+ GPIO(GPIO&&) = delete;
+ GPIO& operator=(const GPIO&) = delete;
+ GPIO& operator=(GPIO&&) = delete;
+ virtual ~GPIO() = default;
+
+ enum class RequestType
+ {
+ Read,
+ Write
+ };
+
+ /**
+ * Request ownership of the GPIO.
+ *
+ * Throws an exception if an error occurs.
+ *
+ * This is required before getting or setting the GPIO value.
+ *
+ * @param type specifies whether requesting to read or write the GPIO
+ */
+ virtual void request(RequestType type) = 0;
+
+ /**
+ * Gets the value of the GPIO.
+ *
+ * Throws an exception if an error occurs.
+ *
+ * @return 0 or 1
+ */
+ virtual int getValue() = 0;
+
+ /**
+ * Sets the value of the GPIO.
+ *
+ * Throws an exception if an error occurs.
+ *
+ * @param value new value (0 or 1)
+ */
+ virtual void setValue(int value) = 0;
+
+ /**
+ * Release ownership of the GPIO.
+ *
+ * Throws an exception if an error occurs.
+ */
+ virtual void release() = 0;
+};
+
+/**
+ * @class BMCGPIO
+ *
+ * Implementation of the GPIO interface using the standard BMC API (libgpiod).
+ */
+class BMCGPIO : public GPIO
+{
+ public:
+ BMCGPIO() = delete;
+ BMCGPIO(const BMCGPIO&) = delete;
+ BMCGPIO(BMCGPIO&&) = delete;
+ BMCGPIO& operator=(const BMCGPIO&) = delete;
+ BMCGPIO& operator=(BMCGPIO&&) = delete;
+ virtual ~BMCGPIO() = default;
+
+ /**
+ * Constructor.
+ *
+ * Throws an exception if a GPIO with the specified name cannot be found.
+ *
+ * @param name GPIO name
+ */
+ explicit BMCGPIO(const std::string& name)
+ {
+ line = gpiod::find_line(name);
+ if (!line)
+ {
+ throw std::invalid_argument{"Invalid GPIO name: " + name};
+ }
+ }
+
+ virtual void request(RequestType type) override
+ {
+ int lineRequestType;
+ if (type == RequestType::Read)
+ {
+ lineRequestType = gpiod::line_request::DIRECTION_INPUT;
+ }
+ else
+ {
+ lineRequestType = gpiod::line_request::DIRECTION_OUTPUT;
+ }
+ line.request({"phosphor-power-control", lineRequestType, 0});
+ }
+
+ virtual int getValue() override
+ {
+ return line.get_value();
+ }
+
+ virtual void setValue(int value) override
+ {
+ line.set_value(value);
+ }
+
+ virtual void release() override
+ {
+ line.release();
+ }
+
+ private:
+ /**
+ * GPIO line to access the pin.
+ */
+ gpiod::line line;
+};
+
+} // namespace phosphor::power::sequencer
diff --git a/phosphor-power-sequencer/test/mock_gpio.hpp b/phosphor-power-sequencer/test/mock_gpio.hpp
new file mode 100644
index 0000000..e68b1de
--- /dev/null
+++ b/phosphor-power-sequencer/test/mock_gpio.hpp
@@ -0,0 +1,46 @@
+/**
+ * Copyright © 2025 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.
+ */
+#pragma once
+
+#include "gpio.hpp"
+
+#include <gmock/gmock.h>
+
+namespace phosphor::power::sequencer
+{
+
+/**
+ * @class MockGPIO
+ *
+ * Mock implementation of the GPIO interface.
+ */
+class MockGPIO : public GPIO
+{
+ public:
+ MockGPIO() = default;
+ MockGPIO(const MockGPIO&) = delete;
+ MockGPIO(MockGPIO&&) = delete;
+ MockGPIO& operator=(const MockGPIO&) = delete;
+ MockGPIO& operator=(MockGPIO&&) = delete;
+ virtual ~MockGPIO() = default;
+
+ MOCK_METHOD(void, request, (RequestType type), (override));
+ MOCK_METHOD(int, getValue, (), (override));
+ MOCK_METHOD(void, setValue, (int value), (override));
+ MOCK_METHOD(void, release, (), (override));
+};
+
+} // namespace phosphor::power::sequencer