Add methods to support setting line configuration. Signed-off-by: Kent Gibson <warthog618@xxxxxxxxx> --- bindings/cxx/gpiod.hpp | 55 +++++++++++++++++++++++++ bindings/cxx/line.cpp | 37 +++++++++++++++++ bindings/cxx/line_bulk.cpp | 83 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 175 insertions(+) diff --git a/bindings/cxx/gpiod.hpp b/bindings/cxx/gpiod.hpp index 2b1a6ab..dcae431 100644 --- a/bindings/cxx/gpiod.hpp +++ b/bindings/cxx/gpiod.hpp @@ -381,6 +381,32 @@ public: */ GPIOD_API void set_value(int val) const; + /** + * @brief Set configuration of this line. + * @param direction New direction. + * @param flags Replacement flags. + * @param value New value (0 or 1) - only matters for OUTPUT direction. + */ + GPIOD_API void set_config(int direction, ::std::bitset<32> flags, + int value = 0) const; + + /** + * @brief Set configuration flags of this line. + * @param flags Replacement flags. + */ + GPIOD_API void set_flags(::std::bitset<32> flags) const; + + /** + * @brief Change the direction this line to input. + */ + GPIOD_API void set_direction_input() const; + + /** + * @brief Change the direction this lines to output. + * @param value New value (0 or 1). + */ + GPIOD_API void set_direction_output(int value = 0) const; + /** * @brief Wait for an event on this line. * @param timeout Time to wait before returning if no event occurred. @@ -648,6 +674,35 @@ public: */ GPIOD_API void set_values(const ::std::vector<int>& values) const; + /** + * @brief Set configuration of all lines held by this object. + * @param direction New direction. + * @param flags Replacement flags. + * @param values Vector of values to set. Must be the same size as the + * number of lines held by this line_bulk. + * Only relevant for output direction requests. + */ + GPIOD_API void set_config(int direction, ::std::bitset<32> flags, + const ::std::vector<int> values = std::vector<int>()) const; + + /** + * @brief Set configuration flags of all lines held by this object. + * @param flags Replacement flags. + */ + GPIOD_API void set_flags(::std::bitset<32> flags) const; + + /** + * @brief Change the direction all lines held by this object to input. + */ + GPIOD_API void set_direction_input() const; + + /** + * @brief Change the direction all lines held by this object to output. + * @param values Vector of values to set. Must be the same size as the + * number of lines held by this line_bulk. + */ + GPIOD_API void set_direction_output(const ::std::vector<int>& values) const; + /** * @brief Poll the set of lines for line events. * @param timeout Number of nanoseconds to wait before returning an diff --git a/bindings/cxx/line.cpp b/bindings/cxx/line.cpp index dd6bb6a..a688b5d 100644 --- a/bindings/cxx/line.cpp +++ b/bindings/cxx/line.cpp @@ -158,6 +158,43 @@ void line::set_value(int val) const bulk.set_values({ val }); } +void line::set_config(int direction, ::std::bitset<32> flags, + int value) const +{ + this->throw_if_null(); + + line_bulk bulk({ *this }); + + bulk.set_config(direction, flags, { value }); +} + +void line::set_flags(::std::bitset<32> flags) const +{ + this->throw_if_null(); + + line_bulk bulk({ *this }); + + bulk.set_flags(flags); +} + +void line::set_direction_input() const +{ + this->throw_if_null(); + + line_bulk bulk({ *this }); + + bulk.set_direction_input(); +} + +void line::set_direction_output(int value) const +{ + this->throw_if_null(); + + line_bulk bulk({ *this }); + + bulk.set_direction_output({ value }); +} + bool line::event_wait(const ::std::chrono::nanoseconds& timeout) const { this->throw_if_null(); diff --git a/bindings/cxx/line_bulk.cpp b/bindings/cxx/line_bulk.cpp index 5f1cac4..6f7d161 100644 --- a/bindings/cxx/line_bulk.cpp +++ b/bindings/cxx/line_bulk.cpp @@ -176,6 +176,89 @@ void line_bulk::set_values(const ::std::vector<int>& values) const "error setting GPIO line values"); } +void line_bulk::set_config(int direction, ::std::bitset<32> flags, + const ::std::vector<int> values) const +{ + this->throw_if_empty(); + + if (!values.empty() && this->_m_bulk.size() != values.size()) + throw ::std::invalid_argument("the number of default values must correspond with the number of lines"); + + ::gpiod_line_bulk bulk; + int rv, gflags; + + gflags = 0; + + for (auto& it: reqflag_mapping) { + if ((it.first & flags).to_ulong()) + gflags |= it.second; + } + + this->to_line_bulk(::std::addressof(bulk)); + + rv = ::gpiod_line_set_config_bulk(::std::addressof(bulk), direction, + gflags, values.data()); + if (rv) + throw ::std::system_error(errno, ::std::system_category(), + "error setting GPIO line config"); +} + +void line_bulk::set_flags(::std::bitset<32> flags) const +{ + this->throw_if_empty(); + + ::gpiod_line_bulk bulk; + int rv, gflags; + + this->to_line_bulk(::std::addressof(bulk)); + + gflags = 0; + + for (auto& it: reqflag_mapping) { + if ((it.first & flags).to_ulong()) + gflags |= it.second; + } + + rv = ::gpiod_line_set_flags_bulk(::std::addressof(bulk), gflags); + if (rv) + throw ::std::system_error(errno, ::std::system_category(), + "error setting GPIO line flags"); +} + +void line_bulk::set_direction_input() const +{ + this->throw_if_empty(); + + ::gpiod_line_bulk bulk; + int rv; + + this->to_line_bulk(::std::addressof(bulk)); + + rv = ::gpiod_line_set_direction_bulk_input(::std::addressof(bulk)); + if (rv) + throw ::std::system_error(errno, ::std::system_category(), + "error setting GPIO line direction to input"); +} + +void line_bulk::set_direction_output(const ::std::vector<int>& values) const +{ + this->throw_if_empty(); + + if (values.size() != this->_m_bulk.size()) + throw ::std::invalid_argument("the size of values array must correspond with the number of lines"); + + ::gpiod_line_bulk bulk; + int rv; + + this->to_line_bulk(::std::addressof(bulk)); + + rv = ::gpiod_line_set_direction_bulk_output(::std::addressof(bulk), + values.data()); + if (rv) + throw ::std::system_error(errno, ::std::system_category(), + "error setting GPIO line direction to output"); +} + line_bulk line_bulk::event_wait(const ::std::chrono::nanoseconds& timeout) const { this->throw_if_empty(); -- 2.24.0