From: Bartosz Golaszewski <bartosz.golaszewski@xxxxxxxxxx> 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@xxxxxxxxxx> --- 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 --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; -- 2.37.2