diff mbox series

[libgpiod,v2,5/8] bindings: cxx: add line_config.set_output_values()

Message ID 20230120094515.40464-6-brgl@bgdev.pl
State Superseded
Headers show
Series treewide: continue beating libgpiod v2 into shape for an upcoming release | expand

Commit Message

Bartosz Golaszewski Jan. 20, 2023, 9:45 a.m. UTC
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

Extend line_config to expose a new method - set_output_values() - which
wraps the new C function for setting multiple output values at once.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
 bindings/cxx/gpiodcxx/line-config.hpp    |  7 ++++
 bindings/cxx/internal.hpp                |  1 +
 bindings/cxx/line-config.cpp             | 15 +++++++
 bindings/cxx/line-settings.cpp           |  5 +++
 bindings/cxx/tests/tests-line-config.cpp | 51 ++++++++++++++++++++++++
 5 files changed, 79 insertions(+)
diff mbox series

Patch

diff --git a/bindings/cxx/gpiodcxx/line-config.hpp b/bindings/cxx/gpiodcxx/line-config.hpp
index a917913..b76fdff 100644
--- a/bindings/cxx/gpiodcxx/line-config.hpp
+++ b/bindings/cxx/gpiodcxx/line-config.hpp
@@ -76,6 +76,13 @@  public:
 	 */
 	line_config& add_line_settings(const line::offsets& offsets, const line_settings& settings);
 
+	/**
+	 * @brief Set output values for a number of lines.
+	 * @param values Buffer containing the output values.
+	 * @return Reference to self.
+	 */
+	line_config& set_output_values(const line::values& values);
+
 	/**
 	 * @brief Get a mapping of offsets to line settings stored by this
 	 *        object.
diff --git a/bindings/cxx/internal.hpp b/bindings/cxx/internal.hpp
index 6aceac1..8322e12 100644
--- a/bindings/cxx/internal.hpp
+++ b/bindings/cxx/internal.hpp
@@ -31,6 +31,7 @@  map_enum_c_to_cxx(c_enum_type value, const ::std::map<c_enum_type, cxx_enum_type
 }
 
 void throw_from_errno(const ::std::string& what);
+::gpiod_line_value map_output_value(line::value value);
 
 template<class T, void F(T*)> struct deleter
 {
diff --git a/bindings/cxx/line-config.cpp b/bindings/cxx/line-config.cpp
index 3ec99f0..233ba33 100644
--- a/bindings/cxx/line-config.cpp
+++ b/bindings/cxx/line-config.cpp
@@ -100,6 +100,21 @@  GPIOD_CXX_API line_config& line_config::add_line_settings(const line::offsets& o
 	return *this;
 }
 
+GPIOD_CXX_API line_config& line_config::set_output_values(const line::values& values)
+{
+	::std::vector<::gpiod_line_value> mapped_values(values.size());
+
+	for (unsigned int i = 0; i < values.size(); i++)
+		mapped_values[i] = map_output_value(values[i]);
+
+	auto ret = ::gpiod_line_config_set_output_values(this->_m_priv->config.get(),
+							 mapped_values.data(), mapped_values.size());
+	if (ret)
+		throw_from_errno("unable to set output values");
+
+	return *this;
+}
+
 GPIOD_CXX_API ::std::map<line::offset, line_settings> line_config::get_line_settings() const
 {
 	::std::size_t num_offsets = ::gpiod_line_config_get_num_configured_offsets(
diff --git a/bindings/cxx/line-settings.cpp b/bindings/cxx/line-settings.cpp
index 32f21a3..2159062 100644
--- a/bindings/cxx/line-settings.cpp
+++ b/bindings/cxx/line-settings.cpp
@@ -139,6 +139,11 @@  cxx_enum_type get_mapped_value(::gpiod_line_settings* settings,
 
 } /* namespace */
 
+::gpiod_line_value map_output_value(line::value value)
+{
+	return do_map_value(value, value_mapping);
+}
+
 line_settings::impl::impl()
 	: settings(make_line_settings())
 {
diff --git a/bindings/cxx/tests/tests-line-config.cpp b/bindings/cxx/tests/tests-line-config.cpp
index 5fa0f94..5e439a1 100644
--- a/bindings/cxx/tests/tests-line-config.cpp
+++ b/bindings/cxx/tests/tests-line-config.cpp
@@ -4,12 +4,17 @@ 
 #include <catch2/catch.hpp>
 #include <gpiod.hpp>
 
+#include "gpiosim.hpp"
 #include "helpers.hpp"
 
+using ::gpiosim::make_sim;
 using namespace ::std::chrono_literals;
 using direction = ::gpiod::line::direction;
 using drive = ::gpiod::line::drive;
 using edge = ::gpiod::line::edge;
+using simval = ::gpiosim::chip::value;
+using value = ::gpiod::line::value;
+using values = ::gpiod::line::values;
 
 namespace {
 
@@ -72,6 +77,52 @@  TEST_CASE("line_config can be reset", "[line-config]")
 	REQUIRE(cfg.get_line_settings().size() == 0);
 }
 
+TEST_CASE("output values can be set globally", "[line-config]")
+{
+	const values vals = { value::ACTIVE, value::INACTIVE, value::ACTIVE, value::INACTIVE };
+
+	auto sim = make_sim()
+		.set_num_lines(4)
+		.build();
+
+	::gpiod::line_config cfg;
+
+	SECTION("request with globally set output values")
+	{
+		cfg
+			.add_line_settings(
+				{0, 1, 2, 3},
+				::gpiod::line_settings().set_direction(direction::OUTPUT)
+			)
+			.set_output_values(vals);
+
+		auto request = ::gpiod::chip(sim.dev_path())
+			.prepare_request()
+			.set_line_config(cfg)
+			.do_request();
+
+		REQUIRE(sim.get_value(0) == simval::ACTIVE);
+		REQUIRE(sim.get_value(1) == simval::INACTIVE);
+		REQUIRE(sim.get_value(2) == simval::ACTIVE);
+		REQUIRE(sim.get_value(3) == simval::INACTIVE);
+	}
+
+	SECTION("read back global output values")
+	{
+		cfg
+			.add_line_settings(
+				{0, 1, 2, 3},
+				::gpiod::line_settings()
+					.set_direction(direction::OUTPUT)
+					.set_output_value(value::ACTIVE)
+			)
+			.set_output_values(vals);
+
+		auto settings = cfg.get_line_settings()[1];
+		REQUIRE(settings.output_value() == value::INACTIVE);
+	}
+}
+
 TEST_CASE("line_config stream insertion operator works", "[line-config]")
 {
 	::gpiod::line_config cfg;