* [libgpiod][PATCH v2 0/8] treewide: continue beating libgpiod v2 into shape for an upcoming release
@ 2023-01-20 9:45 Bartosz Golaszewski
2023-01-20 9:45 ` [libgpiod][PATCH v2 1/8] README: update for libgpiod v2 Bartosz Golaszewski
` (7 more replies)
0 siblings, 8 replies; 11+ messages in thread
From: Bartosz Golaszewski @ 2023-01-20 9:45 UTC (permalink / raw)
To: Kent Gibson, Linus Walleij, Andy Shevchenko, Viresh Kumar
Cc: linux-gpio, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
This series contains an assortment of smaller and bigger changes. Some are
just simple updates to docs, some fix bugs and we have two more changes to
the API: unifying the get_offsets functions for line config and line request
as well as providing an interface for setting multiple output values at once
in line_config before requesting lines.
Rust bindings have also been updated slightly so Viresh please make sure to
take a look and review.
I really hope this is the last set of bigger changes and that I'll be able
to tag an RC and release v2 in the next couple of weeks.
v1 -> v2:
- apply non-controversial patches and drop them from the series
- fix README as per Andy's suggestions
- extend the test cases for gpiod_line_config/request_get_offsets()
- improve rust code for getting line settings from line config
- improve the documentation for gpiod_line_config_set_output_values()
- extend the python support for setting global output values by allowing
to pass mappings from line names/offsets to line values
Bartosz Golaszewski (8):
README: update for libgpiod v2
treewide: unify gpiod_line_config/request_get_offsets() functions
core: provide gpiod_line_config_set_output_values()
gpioset: use gpiod_line_config_set_output_values()
bindings: cxx: add line_config.set_output_values()
bindings: python: add the output_values argument to
Chip.request_lines()
bindings: rust: make mutators return &mut self
bindings: rust: provide line_config.set_output_values()
README | 33 ++--
bindings/cxx/gpiodcxx/line-config.hpp | 7 +
bindings/cxx/internal.hpp | 1 +
bindings/cxx/line-config.cpp | 33 ++--
bindings/cxx/line-request.cpp | 6 +-
bindings/cxx/line-settings.cpp | 5 +
bindings/cxx/tests/tests-line-config.cpp | 51 +++++++
bindings/python/gpiod/chip.py | 30 ++++
bindings/python/gpiod/ext/line-config.c | 64 ++++++++
bindings/python/gpiod/ext/request.c | 8 +-
bindings/python/tests/tests_line_request.py | 55 +++++++
.../rust/libgpiod/examples/gpio_events.rs | 2 +-
.../examples/gpio_threaded_info_events.rs | 6 +-
bindings/rust/libgpiod/examples/gpioget.rs | 4 +-
bindings/rust/libgpiod/examples/gpiomon.rs | 2 +-
bindings/rust/libgpiod/examples/gpioset.rs | 4 +-
bindings/rust/libgpiod/src/lib.rs | 1 +
bindings/rust/libgpiod/src/line_config.rs | 84 +++++-----
bindings/rust/libgpiod/src/line_request.rs | 24 +--
bindings/rust/libgpiod/src/request_config.rs | 8 +-
bindings/rust/libgpiod/tests/common/config.rs | 8 +-
bindings/rust/libgpiod/tests/info_event.rs | 6 +-
bindings/rust/libgpiod/tests/line_config.rs | 76 ++++++++--
bindings/rust/libgpiod/tests/line_request.rs | 73 ++++-----
.../rust/libgpiod/tests/request_config.rs | 2 +-
configure.ac | 1 +
include/gpiod.h | 87 ++++++++---
lib/line-config.c | 97 +++++++++---
lib/line-request.c | 23 ++-
tests/gpiod-test-helpers.h | 10 ++
tests/tests-line-config.c | 143 +++++++++++++++---
tests/tests-line-request.c | 49 +++++-
tools/gpioset.c | 21 +--
33 files changed, 777 insertions(+), 247 deletions(-)
--
2.37.2
^ permalink raw reply [flat|nested] 11+ messages in thread
* [libgpiod][PATCH v2 1/8] README: update for libgpiod v2
2023-01-20 9:45 [libgpiod][PATCH v2 0/8] treewide: continue beating libgpiod v2 into shape for an upcoming release Bartosz Golaszewski
@ 2023-01-20 9:45 ` Bartosz Golaszewski
2023-01-20 9:45 ` [libgpiod][PATCH v2 2/8] treewide: unify gpiod_line_config/request_get_offsets() functions Bartosz Golaszewski
` (6 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Bartosz Golaszewski @ 2023-01-20 9:45 UTC (permalink / raw)
To: Kent Gibson, Linus Walleij, Andy Shevchenko, Viresh Kumar
Cc: linux-gpio, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Certain parts of the README file still refer to concepts removed from
libgpiod v2. Update whatever needs updating.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
README | 33 +++++++++++++++++----------------
1 file changed, 17 insertions(+), 16 deletions(-)
diff --git a/README b/README
index d51d701..b71739e 100644
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: CC-BY-SA-4.0
-# SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
+# SPDX-FileCopyrightText: 2017-2023 Bartosz Golaszewski <brgl@bgdev.pl>
libgpiod
========
@@ -30,14 +30,10 @@ allow an easy conversion of user scripts to using the character device.
BUILDING
--------
-This is a pretty standard autotools project. It does not depend on any
-libraries other than the standard C library with GNU extensions.
+This is a pretty standard autotools project. The core C library does not have
+any external dependencies other than the standard C library with GNU extensions.
-The autoconf version needed to compile the project is 2.61.
-
-Recent kernel headers are also required for the GPIO user API definitions. For
-the exact version of kernel headers required, please refer to the configure.ac
-contents.
+The command-line tools optionally depend on libedit for the interactive feature.
To build the project (including command-line utilities) run:
@@ -51,6 +47,8 @@ arguments to it.
If building from release tarballs, the configure script is already provided and
there's no need to invoke autogen.sh.
+For all configure features, see: ./configure --help.
+
TOOLS
-----
@@ -231,10 +229,10 @@ interface.
The minimum kernel version required to run the tests can be checked in the
tests/gpiod-test.c source file (it's subject to change if new features are
-added to the kernel). The tests work together with the gpio-mockup kernel
-module which must be enabled. NOTE: the module must not be built-in. A helper
-library - libgpiomockup - is included to enable straightforward interaction
-with the module.
+added to the kernel). The tests work together with the gpio-sim kernel module
+which must either be built-in or available for loading using kmod. A helper
+library - libgpiosim - is included to enable straightforward interaction with
+the module.
To build the testing executable add the '--enable-tests' option when running
the configure script. If enabled, the tests will be installed next to
@@ -251,12 +249,13 @@ The gpio-tools programs can be tested separately using the gpio-tools-test.bats
script. It requires bats[1] to run and assumes that the tested executables are
in the same directory as the script.
-Both C++ and Python bindings also include their own test-suites. Both reuse the
-libgpiomockup library to avoid code duplication when interacting with
-gpio-mockup.
+C++, Rust and Python bindings also include their own test-suites. All three
+reuse the libgpiosim library to avoid code duplication when interacting with
+gpio-sim.
Python test-suite uses the standard unittest package. C++ tests use an external
-testing framework - Catch2 - which must be installed in the system.
+testing framework - Catch2 - which must be installed in the system. Rust
+bindings use the standard tests module layout and the #[test] attribute.
DOCUMENTATION
-------------
@@ -268,6 +267,8 @@ doxygen markup blocks. Doxygen documentation can be generated by executing
Python bindings contain help strings that can be accessed with the help
builtin.
+Rust bindings use rustdoc.
+
Man pages for command-line programs are generated automatically if gpio-tools
were selected and help2man is available in the system.
--
2.37.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [libgpiod][PATCH v2 2/8] treewide: unify gpiod_line_config/request_get_offsets() functions
2023-01-20 9:45 [libgpiod][PATCH v2 0/8] treewide: continue beating libgpiod v2 into shape for an upcoming release Bartosz Golaszewski
2023-01-20 9:45 ` [libgpiod][PATCH v2 1/8] README: update for libgpiod v2 Bartosz Golaszewski
@ 2023-01-20 9:45 ` Bartosz Golaszewski
2023-01-20 9:45 ` [libgpiod][PATCH v2 3/8] core: provide gpiod_line_config_set_output_values() Bartosz Golaszewski
` (5 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Bartosz Golaszewski @ 2023-01-20 9:45 UTC (permalink / raw)
To: Kent Gibson, Linus Walleij, Andy Shevchenko, Viresh Kumar
Cc: linux-gpio, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
We have two functions in the C API that allow users to retrieve a list
of offsets from objects: gpiod_line_request_get_offsets() and
gpiod_line_config_get_offsets(). Even though they serve pretty much the
same purpose, they have different signatures and one of them also
requires the user to free the memory allocated within the libgpiod
library with a non-libgpiod free() function.
Unify them: make them take the array in which to store offsets and the
size of this array. Make them return the number of offsets actually
stored in the array and make them impossible to fail. Change their names
to be more descriptive and in the case of line_config: add a new function
that allows users to get the number of configured offsets.
Update the entire tree to use the new interfaces.
For rust bindings: also unify the line config interface to return a map
of line settings like C++ bindings do instead of having a function to
get settings by offset. A map returned from a single call is easier to
iterate over with a for loop than using an integer and calling the
previous line_settings() method.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
bindings/cxx/line-config.cpp | 18 ++---
bindings/cxx/line-request.cpp | 6 +-
bindings/python/gpiod/ext/request.c | 8 +--
bindings/rust/libgpiod/src/line_config.rs | 72 ++++++++-----------
bindings/rust/libgpiod/src/line_request.rs | 8 ++-
bindings/rust/libgpiod/tests/line_config.rs | 24 ++-----
configure.ac | 1 +
include/gpiod.h | 62 +++++++++++------
lib/line-config.c | 39 +++++------
lib/line-request.c | 23 ++++---
tests/tests-line-config.c | 76 +++++++++++++++------
tests/tests-line-request.c | 49 +++++++++++--
12 files changed, 227 insertions(+), 159 deletions(-)
diff --git a/bindings/cxx/line-config.cpp b/bindings/cxx/line-config.cpp
index f7f1bfa..3ec99f0 100644
--- a/bindings/cxx/line-config.cpp
+++ b/bindings/cxx/line-config.cpp
@@ -102,31 +102,27 @@ GPIOD_CXX_API line_config& line_config::add_line_settings(const line::offsets& o
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(
+ this->_m_priv->config.get());
::std::map<line::offset, line_settings> settings_map;
- ::std::size_t num_offsets;
- unsigned int *offsets_ptr;
- int ret;
-
- ret = ::gpiod_line_config_get_offsets(this->_m_priv->config.get(),
- &num_offsets, &offsets_ptr);
- if (ret)
- throw_from_errno("unable to retrieve line offsets");
+ ::std::vector<unsigned int> offsets(num_offsets);
if (num_offsets == 0)
return settings_map;
- ::std::unique_ptr<unsigned int, malloc_deleter> offsets(offsets_ptr);
+ ::gpiod_line_config_get_configured_offsets(this->_m_priv->config.get(),
+ offsets.data(), num_offsets);
for (size_t i = 0; i < num_offsets; i++) {
line_settings settings;
settings._m_priv->settings.reset(::gpiod_line_config_get_line_settings(
this->_m_priv->config.get(),
- offsets.get()[i]));
+ offsets[i]));
if (!settings._m_priv->settings)
throw_from_errno("unable to retrieve line settings");
- settings_map[offsets.get()[i]] = ::std::move(settings);
+ settings_map[offsets[i]] = ::std::move(settings);
}
return settings_map;
diff --git a/bindings/cxx/line-request.cpp b/bindings/cxx/line-request.cpp
index b52ceaf..b0723c3 100644
--- a/bindings/cxx/line-request.cpp
+++ b/bindings/cxx/line-request.cpp
@@ -18,7 +18,7 @@ void line_request::impl::throw_if_released() const
void line_request::impl::set_request_ptr(line_request_ptr& ptr)
{
this->request = ::std::move(ptr);
- this->offset_buf.resize(::gpiod_line_request_get_num_lines(this->request.get()));
+ this->offset_buf.resize(::gpiod_line_request_get_num_requested_lines(this->request.get()));
}
void line_request::impl::fill_offset_buf(const line::offsets& offsets)
@@ -67,7 +67,7 @@ GPIOD_CXX_API ::std::size_t line_request::num_lines() const
{
this->_m_priv->throw_if_released();
- return ::gpiod_line_request_get_num_lines(this->_m_priv->request.get());
+ return ::gpiod_line_request_get_num_requested_lines(this->_m_priv->request.get());
}
GPIOD_CXX_API line::offsets line_request::offsets() const
@@ -78,7 +78,7 @@ GPIOD_CXX_API line::offsets line_request::offsets() const
::std::vector<unsigned int> buf(num_lines);
line::offsets offsets(num_lines);
- ::gpiod_line_request_get_offsets(this->_m_priv->request.get(), buf.data());
+ ::gpiod_line_request_get_requested_offsets(this->_m_priv->request.get(), buf.data(), buf.size());
for (unsigned int i = 0; i < num_lines; i++)
offsets[i] = buf[i];
diff --git a/bindings/python/gpiod/ext/request.c b/bindings/python/gpiod/ext/request.c
index d3e1448..a32ff8f 100644
--- a/bindings/python/gpiod/ext/request.c
+++ b/bindings/python/gpiod/ext/request.c
@@ -41,7 +41,7 @@ static PyObject *
request_num_lines(request_object *self, void *Py_UNUSED(ignored))
{
return PyLong_FromUnsignedLong(
- gpiod_line_request_get_num_lines(self->request));
+ gpiod_line_request_get_num_requested_lines(self->request));
}
static PyObject *request_offsets(request_object *self, void *Py_UNUSED(ignored))
@@ -51,13 +51,13 @@ static PyObject *request_offsets(request_object *self, void *Py_UNUSED(ignored))
size_t num_lines, i;
int ret;
- num_lines = gpiod_line_request_get_num_lines(self->request);
+ num_lines = gpiod_line_request_get_num_requested_lines(self->request);
offsets = PyMem_Calloc(num_lines, sizeof(unsigned int));
if (!offsets)
return PyErr_NoMemory();
- gpiod_line_request_get_offsets(self->request, offsets);
+ gpiod_line_request_get_requested_offsets(self->request, offsets, num_lines);
lines = PyList_New(num_lines);
if (!lines) {
@@ -365,7 +365,7 @@ PyObject *Py_gpiod_MakeRequestObject(struct gpiod_line_request *request,
unsigned int *offsets;
size_t num_lines;
- num_lines = gpiod_line_request_get_num_lines(request);
+ num_lines = gpiod_line_request_get_num_requested_lines(request);
req_obj = PyObject_New(request_object, &request_type);
if (!req_obj)
diff --git a/bindings/rust/libgpiod/src/line_config.rs b/bindings/rust/libgpiod/src/line_config.rs
index 19dc187..42dad9f 100644
--- a/bindings/rust/libgpiod/src/line_config.rs
+++ b/bindings/rust/libgpiod/src/line_config.rs
@@ -2,8 +2,8 @@
// SPDX-FileCopyrightText: 2022 Linaro Ltd.
// SPDX-FileCopyrightTest: 2022 Viresh Kumar <viresh.kumar@linaro.org>
-use std::os::raw::{c_ulong, c_void};
-use std::slice;
+use std::os::raw::c_ulong;
+use std::collections::HashMap;
use super::{
gpiod,
@@ -77,51 +77,33 @@ impl Config {
}
}
- /// Get line settings for offset.
- pub fn line_settings(&self, offset: Offset) -> Result<Settings> {
- // SAFETY: `gpiod_line_config` is guaranteed to be valid here.
- let settings = unsafe { gpiod::gpiod_line_config_get_line_settings(self.config, offset) };
-
- if settings.is_null() {
- return Err(Error::OperationFailed(
- OperationType::LineConfigGetSettings,
- errno::errno(),
- ));
+ /// Get a mapping of offsets to line settings stored by this object.
+ pub fn line_settings(&self) -> Result<HashMap<Offset, Settings>> {
+ let mut map: HashMap<Offset, Settings> = HashMap::new();
+ let num_lines = unsafe { gpiod::gpiod_line_config_get_num_configured_offsets(self.config) };
+ let mut offsets = vec![0; num_lines as usize];
+
+ // SAFETY: gpiod_line_config is guaranteed to be valid here.
+ let num_stored = unsafe { gpiod::gpiod_line_config_get_configured_offsets(
+ self.config,
+ offsets.as_mut_ptr(),
+ num_lines) };
+
+ for offset in &offsets[0..num_stored as usize] {
+ // SAFETY: `gpiod_line_config` is guaranteed to be valid here.
+ let settings = unsafe { gpiod::gpiod_line_config_get_line_settings(self.config,
+ *offset) };
+ if settings.is_null() {
+ return Err(Error::OperationFailed(
+ OperationType::LineConfigGetSettings,
+ errno::errno(),
+ ));
+ }
+
+ map.insert(*offset, Settings::new_with_settings(settings));
}
- Ok(Settings::new_with_settings(settings))
- }
-
- /// Get configured offsets.
- pub fn offsets(&self) -> Result<Vec<Offset>> {
- let mut num: u64 = 0;
- let mut ptr: *mut Offset = std::ptr::null_mut();
-
- // SAFETY: The `ptr` array returned by libgpiod is guaranteed to live as long
- // as it is not explicitly freed with `free()`.
- let ret = unsafe {
- gpiod::gpiod_line_config_get_offsets(
- self.config,
- &mut num as *mut _ as *mut _,
- &mut ptr,
- )
- };
-
- if ret == -1 {
- return Err(Error::OperationFailed(
- OperationType::LineConfigGetOffsets,
- errno::errno(),
- ));
- }
-
- // SAFETY: The `ptr` array returned by libgpiod is guaranteed to live as long
- // as it is not explicitly freed with `free()`.
- let offsets = unsafe { slice::from_raw_parts(ptr as *const Offset, num as usize).to_vec() };
-
- // SAFETY: The `ptr` array is guaranteed to be valid here.
- unsafe { libc::free(ptr as *mut c_void) };
-
- Ok(offsets)
+ Ok(map)
}
}
diff --git a/bindings/rust/libgpiod/src/line_request.rs b/bindings/rust/libgpiod/src/line_request.rs
index d9e041c..7915924 100644
--- a/bindings/rust/libgpiod/src/line_request.rs
+++ b/bindings/rust/libgpiod/src/line_request.rs
@@ -28,7 +28,7 @@ impl Request {
/// Get the number of lines in the request.
pub fn num_lines(&self) -> usize {
// SAFETY: `gpiod_line_request` is guaranteed to be valid here.
- unsafe { gpiod::gpiod_line_request_get_num_lines(self.request) as usize }
+ unsafe { gpiod::gpiod_line_request_get_num_requested_lines(self.request) as usize }
}
/// Get the offsets of lines in the request.
@@ -36,7 +36,11 @@ impl Request {
let mut offsets = vec![0; self.num_lines() as usize];
// SAFETY: `gpiod_line_request` is guaranteed to be valid here.
- unsafe { gpiod::gpiod_line_request_get_offsets(self.request, offsets.as_mut_ptr()) };
+ let num_offsets = unsafe { gpiod::gpiod_line_request_get_requested_offsets(
+ self.request,
+ offsets.as_mut_ptr(),
+ self.num_lines() as u64) };
+ offsets.shrink_to(num_offsets as usize);
offsets
}
diff --git a/bindings/rust/libgpiod/tests/line_config.rs b/bindings/rust/libgpiod/tests/line_config.rs
index bebf106..95f2178 100644
--- a/bindings/rust/libgpiod/tests/line_config.rs
+++ b/bindings/rust/libgpiod/tests/line_config.rs
@@ -37,8 +37,10 @@ mod line_config {
lconfig.add_line_settings(&[0, 1, 2], lsettings1).unwrap();
lconfig.add_line_settings(&[4, 5], lsettings2).unwrap();
+ let settings_map = lconfig.line_settings().unwrap();
+
// Retrieve settings
- let lsettings = lconfig.line_settings(1).unwrap();
+ let lsettings = settings_map.get(&1).unwrap();
assert_eq!(
lsettings.prop(SettingKind::Direction).unwrap(),
SettingVal::Direction(Direction::Input)
@@ -56,7 +58,7 @@ mod line_config {
SettingVal::Drive(Drive::PushPull)
);
- let lsettings = lconfig.line_settings(5).unwrap();
+ let lsettings = settings_map.get(&5).unwrap();
assert_eq!(
lsettings.prop(SettingKind::Direction).unwrap(),
SettingVal::Direction(Direction::Output)
@@ -74,22 +76,4 @@ mod line_config {
SettingVal::OutputValue(Value::Active)
);
}
-
- #[test]
- fn offsets() {
- let mut lsettings1 = line::Settings::new().unwrap();
- lsettings1.set_direction(Direction::Input).unwrap();
-
- let mut lsettings2 = line::Settings::new().unwrap();
- lsettings2.set_event_clock(EventClock::Realtime).unwrap();
-
- // Add settings for multiple lines
- let lconfig = line::Config::new().unwrap();
- lconfig.add_line_settings(&[0, 1, 2], lsettings1).unwrap();
- lconfig.add_line_settings(&[4, 5], lsettings2).unwrap();
-
- // Verify offsets
- let offsets = lconfig.offsets().unwrap();
- assert_eq!(offsets, [0, 1, 2, 4, 5]);
- }
}
diff --git a/configure.ac b/configure.ac
index 4a91723..c5fb7c7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -88,6 +88,7 @@ AC_CHECK_HEADERS([dirent.h], [], [HEADER_NOT_FOUND_LIB([dirent.h])])
AC_CHECK_HEADERS([poll.h], [], [HEADER_NOT_FOUND_LIB([poll.h])])
AC_CHECK_HEADERS([sys/sysmacros.h], [], [HEADER_NOT_FOUND_LIB([sys/sysmacros.h])])
AC_CHECK_HEADERS([sys/ioctl.h], [], [HEADER_NOT_FOUND_LIB([sys/ioctl.h])])
+AC_CHECK_HEADERS([sys/param.h], [], [HEADER_NOT_FOUND_LIB([sys/param.h])])
AC_CHECK_HEADERS([sys/stat.h], [], [HEADER_NOT_FOUND_LIB([sys/stat.h])])
AC_CHECK_HEADERS([sys/types.h], [], [HEADER_NOT_FOUND_LIB([sys/types.h])])
AC_CHECK_HEADERS([linux/const.h], [], [HEADER_NOT_FOUND_LIB([linux/const.h])])
diff --git a/include/gpiod.h b/include/gpiod.h
index ff3618d..fea2076 100644
--- a/include/gpiod.h
+++ b/include/gpiod.h
@@ -785,19 +785,29 @@ struct gpiod_line_settings *
gpiod_line_config_get_line_settings(struct gpiod_line_config *config,
unsigned int offset);
+/**
+ * @brief Get the number of configured line offsets.
+ * @param config Line config object.
+ * @return Number of offsets for which line settings have been added.
+ */
+size_t
+gpiod_line_config_get_num_configured_offsets(struct gpiod_line_config *config);
+
/**
* @brief Get configured offsets.
* @param config Line config object.
- * @param num_offsets Pointer to a variable in which the number of line offsets
- * will be stored.
- * @param offsets Pointer to a pointer which will be set to point to an array
- * containing the configured offsets. The array will be allocated
- * using malloc() and must be freed using free().
- * @return 0 on success, -1 on failure.
+ * @param offsets Array to store offsets.
+ * @param max_offsets Number of offsets that can be stored in the offsets array.
+ * @return Number of offsets stored in the offsets array.
+ *
+ * If max_offsets is lower than the number of lines actually requested (this
+ * value can be retrieved using ::gpiod_line_config_get_num_configured_offsets),
+ * then only up to max_lines offsets will be stored in offsets.
*/
-int gpiod_line_config_get_offsets(struct gpiod_line_config *config,
- size_t *num_offsets,
- unsigned int **offsets);
+size_t
+gpiod_line_config_get_configured_offsets(struct gpiod_line_config *config,
+ unsigned int *offsets,
+ size_t max_offsets);
/**
* @}
@@ -885,16 +895,24 @@ void gpiod_line_request_release(struct gpiod_line_request *request);
* @param request Line request object.
* @return Number of requested lines.
*/
-size_t gpiod_line_request_get_num_lines(struct gpiod_line_request *request);
+size_t
+gpiod_line_request_get_num_requested_lines(struct gpiod_line_request *request);
/**
* @brief Get the offsets of the lines in the request.
* @param request Line request object.
- * @param offsets Array to store offsets. Must be sized to hold the number of
- * lines returned by ::gpiod_line_request_get_num_lines.
+ * @param offsets Array to store offsets.
+ * @param max_offsets Number of offsets that can be stored in the offsets array.
+ * @return Number of offsets stored in the offsets array.
+ *
+ * If max_offsets is lower than the number of lines actually requested (this
+ * value can be retrieved using ::gpiod_line_request_get_num_requested_lines),
+ * then only up to max_lines offsets will be stored in offsets.
*/
-void gpiod_line_request_get_offsets(struct gpiod_line_request *request,
- unsigned int *offsets);
+size_t
+gpiod_line_request_get_requested_offsets(struct gpiod_line_request *request,
+ unsigned int *offsets,
+ size_t max_offsets);
/**
* @brief Get the value of a single requested line.
@@ -926,11 +944,11 @@ int gpiod_line_request_get_values_subset(struct gpiod_line_request *request,
* @brief Get the values of all requested lines.
* @param request GPIO line request.
* @param values Array in which the values will be stored. Must be sized to
- * hold the number of lines returned by
- * ::gpiod_line_request_get_num_lines.
+ * hold the number of lines filled by
+ * ::gpiod_line_request_get_num_requested_lines.
* Each value is associated with the line identified by the
- * corresponding entry in the offset array returned by
- * ::gpiod_line_request_get_offsets.
+ * corresponding entry in the offset array filled by
+ * ::gpiod_line_request_get_requested_offsets.
* @return 0 on success, -1 on failure.
*/
int gpiod_line_request_get_values(struct gpiod_line_request *request,
@@ -967,11 +985,11 @@ int gpiod_line_request_set_values_subset(struct gpiod_line_request *request,
* @brief Set the values of all lines associated with a request.
* @param request GPIO line request.
* @param values Array containing the values to set. Must be sized to
- * contain the number of lines returned by
- * ::gpiod_line_request_get_num_lines.
+ * contain the number of lines filled by
+ * ::gpiod_line_request_get_num_requested_lines.
* Each value is associated with the line identified by the
- * corresponding entry in the offset array returned by
- * ::gpiod_line_request_get_offsets.
+ * corresponding entry in the offset array filled by
+ * ::gpiod_line_request_get_requested_offsets.
*/
int gpiod_line_request_set_values(struct gpiod_line_request *request,
const enum gpiod_line_value *values);
diff --git a/lib/line-config.c b/lib/line-config.c
index bc10059..877e7ef 100644
--- a/lib/line-config.c
+++ b/lib/line-config.c
@@ -6,6 +6,7 @@
#include <gpiod.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/param.h>
#include "internal.h"
@@ -152,36 +153,32 @@ gpiod_line_config_get_line_settings(struct gpiod_line_config *config,
return NULL;
}
-GPIOD_API int gpiod_line_config_get_offsets(struct gpiod_line_config *config,
- size_t *num_offsets,
- unsigned int **offsets)
+GPIOD_API size_t
+gpiod_line_config_get_num_configured_offsets(struct gpiod_line_config *config)
{
- unsigned int *offs;
- size_t i;
-
assert(config);
- if (!num_offsets || !offsets) {
- errno = EINVAL;
- return -1;
- }
+ return config->num_configs;
+}
- *num_offsets = config->num_configs;
- *offsets = NULL;
+GPIOD_API size_t
+gpiod_line_config_get_configured_offsets(struct gpiod_line_config *config,
+ unsigned int *offsets,
+ size_t max_offsets)
+{
+ size_t num_offsets, i;
- if (!config->num_configs)
- return 0;
+ assert(config);
- offs = calloc(config->num_configs, sizeof(unsigned int));
- if (!offs)
- return -1;
+ if (!offsets || !max_offsets || !config->num_configs)
+ return 0;
- for (i = 0; i < config->num_configs; i++)
- offs[i] = config->line_configs[i].offset;
+ num_offsets = MIN(config->num_configs, max_offsets);
- *offsets = offs;
+ for (i = 0; i < num_offsets; i++)
+ offsets[i] = config->line_configs[i].offset;
- return 0;
+ return num_offsets;
}
static void set_offsets(struct gpiod_line_config *config,
diff --git a/lib/line-request.c b/lib/line-request.c
index c9ad337..e536355 100644
--- a/lib/line-request.c
+++ b/lib/line-request.c
@@ -7,6 +7,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
+#include <sys/param.h>
#include <unistd.h>
#include "internal.h"
@@ -45,24 +46,30 @@ GPIOD_API void gpiod_line_request_release(struct gpiod_line_request *request)
}
GPIOD_API size_t
-gpiod_line_request_get_num_lines(struct gpiod_line_request *request)
+gpiod_line_request_get_num_requested_lines(struct gpiod_line_request *request)
{
assert(request);
return request->num_lines;
}
-GPIOD_API void
-gpiod_line_request_get_offsets(struct gpiod_line_request *request,
- unsigned int *offsets)
+GPIOD_API size_t
+gpiod_line_request_get_requested_offsets(struct gpiod_line_request *request,
+ unsigned int *offsets,
+ size_t max_offsets)
{
+ size_t num_offsets;
+
assert(request);
- if (!offsets)
- return;
+ if (!offsets || !max_offsets)
+ return 0;
+
+ num_offsets = MIN(request->num_lines, max_offsets);
+
+ memcpy(offsets, request->offsets, sizeof(*offsets) * num_offsets);
- memcpy(offsets, request->offsets,
- sizeof(*offsets) * request->num_lines);
+ return num_offsets;
}
GPIOD_API enum gpiod_line_value
diff --git a/tests/tests-line-config.c b/tests/tests-line-config.c
index 2305810..a1a587d 100644
--- a/tests/tests-line-config.c
+++ b/tests/tests-line-config.c
@@ -185,10 +185,8 @@ GPIOD_TEST_CASE(get_offsets)
{
g_autoptr(struct_gpiod_line_settings) settings = NULL;
g_autoptr(struct_gpiod_line_config) config = NULL;
- g_autofree guint *config_offs = NULL;
- guint offsets[8];
+ guint offsets[8], offsets_in[4];
size_t num_offsets;
- gint ret;
settings = gpiod_test_create_line_settings_or_fail();
config = gpiod_test_create_line_config_or_fail();
@@ -206,39 +204,79 @@ GPIOD_TEST_CASE(get_offsets)
gpiod_test_line_config_add_line_settings_or_fail(config, offsets, 2,
settings);
- ret = gpiod_line_config_get_offsets(config, &num_offsets, &config_offs);
- g_assert_cmpint(ret, ==, 0);
+ num_offsets = gpiod_line_config_get_configured_offsets(config,
+ offsets_in, 4);
g_assert_cmpuint(num_offsets, ==, 4);
- g_assert_cmpuint(config_offs[0], ==, 2);
- g_assert_cmpuint(config_offs[1], ==, 4);
- g_assert_cmpuint(config_offs[2], ==, 6);
- g_assert_cmpuint(config_offs[3], ==, 7);
+ g_assert_cmpuint(offsets_in[0], ==, 2);
+ g_assert_cmpuint(offsets_in[1], ==, 4);
+ g_assert_cmpuint(offsets_in[2], ==, 6);
+ g_assert_cmpuint(offsets_in[3], ==, 7);
}
GPIOD_TEST_CASE(get_0_offsets)
{
g_autoptr(struct_gpiod_line_config) config = NULL;
- g_autofree guint *offsets = NULL;
size_t num_offsets;
- gint ret;
+ guint offsets[3];
config = gpiod_test_create_line_config_or_fail();
- ret = gpiod_line_config_get_offsets(config, &num_offsets, &offsets);
- g_assert_cmpint(ret, ==, 0);
+ num_offsets = gpiod_line_config_get_configured_offsets(config,
+ offsets, 0);
g_assert_cmpuint(num_offsets, ==, 0);
- g_assert_null(offsets);
}
GPIOD_TEST_CASE(get_null_offsets)
{
g_autoptr(struct_gpiod_line_config) config = NULL;
- g_autofree guint *offsets = NULL;
- gint ret;
+ size_t num_offsets;
config = gpiod_test_create_line_config_or_fail();
- ret = gpiod_line_config_get_offsets(config, NULL, &offsets);
- g_assert_cmpint(ret, ==, -1);
- gpiod_test_expect_errno(EINVAL);
+ num_offsets = gpiod_line_config_get_configured_offsets(config,
+ NULL, 10);
+ g_assert_cmpuint(num_offsets, ==, 0);
+}
+
+GPIOD_TEST_CASE(get_less_offsets_than_configured)
+{
+ static const guint offsets[] = { 0, 1, 2, 3 };
+
+ g_autoptr(struct_gpiod_line_config) config = NULL;
+ size_t num_retrieved;
+ guint retrieved[3];
+
+ config = gpiod_test_create_line_config_or_fail();
+
+ gpiod_test_line_config_add_line_settings_or_fail(config, offsets, 4,
+ NULL);
+
+ num_retrieved = gpiod_line_config_get_configured_offsets(config,
+ retrieved, 3);
+ g_assert_cmpuint(num_retrieved, ==, 3);
+ g_assert_cmpuint(retrieved[0], ==, 0);
+ g_assert_cmpuint(retrieved[1], ==, 1);
+ g_assert_cmpuint(retrieved[2], ==, 2);
+}
+
+GPIOD_TEST_CASE(get_more_offsets_than_configured)
+{
+ static const guint offsets[] = { 0, 1, 2, 3 };
+
+ g_autoptr(struct_gpiod_line_config) config = NULL;
+ size_t num_retrieved;
+ guint retrieved[8];
+
+ config = gpiod_test_create_line_config_or_fail();
+
+ gpiod_test_line_config_add_line_settings_or_fail(config, offsets, 4,
+ NULL);
+
+ num_retrieved = gpiod_line_config_get_configured_offsets(config,
+ retrieved, 8);
+ g_assert_cmpuint(num_retrieved, ==, 4);
+ g_assert_cmpuint(retrieved[0], ==, 0);
+ g_assert_cmpuint(retrieved[1], ==, 1);
+ g_assert_cmpuint(retrieved[2], ==, 2);
+ g_assert_cmpuint(retrieved[3], ==, 3);
}
diff --git a/tests/tests-line-request.c b/tests/tests-line-request.c
index 2c2af01..49e9791 100644
--- a/tests/tests-line-request.c
+++ b/tests/tests-line-request.c
@@ -45,9 +45,10 @@ GPIOD_TEST_CASE(request_fails_with_duplicate_offsets)
request = gpiod_chip_request_lines(chip, NULL, line_cfg);
g_assert_nonnull(request);
- num_requested_offsets = gpiod_line_request_get_num_lines(request);
+ num_requested_offsets =
+ gpiod_line_request_get_num_requested_lines(request);
g_assert_cmpuint(num_requested_offsets, ==, 3);
- gpiod_line_request_get_offsets(request, requested_offsets);
+ gpiod_line_request_get_requested_offsets(request, requested_offsets, 4);
g_assert_cmpuint(requested_offsets[0], ==, 0);
g_assert_cmpuint(requested_offsets[1], ==, 2);
g_assert_cmpuint(requested_offsets[2], ==, 3);
@@ -401,9 +402,10 @@ GPIOD_TEST_CASE(num_lines_and_offsets)
request = gpiod_test_request_lines_or_fail(chip, NULL, line_cfg);
- g_assert_cmpuint(gpiod_line_request_get_num_lines(request), ==, 8);
+ g_assert_cmpuint(gpiod_line_request_get_num_requested_lines(request),
+ ==, 8);
gpiod_test_return_if_failed();
- gpiod_line_request_get_offsets(request, read_back);
+ gpiod_line_request_get_requested_offsets(request, read_back, 8);
for (i = 0; i < 8; i++)
g_assert_cmpuint(read_back[i], ==, offsets[i]);
}
@@ -578,3 +580,42 @@ GPIOD_TEST_CASE(request_with_bias_set_to_pull_up)
g_assert_cmpint(g_gpiosim_chip_get_value(sim, 3), ==,
GPIOD_LINE_VALUE_ACTIVE);
}
+
+GPIOD_TEST_CASE(get_requested_offsets_less_and_more)
+{
+ static const guint offsets[] = { 0, 1, 2, 3 };
+
+ g_autoptr(GPIOSimChip) sim = g_gpiosim_chip_new("num-lines", 8, NULL);
+ g_autoptr(struct_gpiod_chip) chip = NULL;
+ g_autoptr(struct_gpiod_line_config) line_cfg = NULL;
+ g_autoptr(struct_gpiod_line_request) request = NULL;
+ size_t num_retrieved;
+ guint retrieved[6];
+
+ chip = gpiod_test_open_chip_or_fail(g_gpiosim_chip_get_dev_path(sim));
+ line_cfg = gpiod_test_create_line_config_or_fail();
+
+ gpiod_test_line_config_add_line_settings_or_fail(line_cfg, offsets, 4,
+ NULL);
+
+ request = gpiod_test_request_lines_or_fail(chip, NULL, line_cfg);
+
+ num_retrieved = gpiod_line_request_get_requested_offsets(request,
+ retrieved, 3);
+
+ g_assert_cmpuint(num_retrieved, ==, 3);
+ g_assert_cmpuint(retrieved[0], ==, 0);
+ g_assert_cmpuint(retrieved[1], ==, 1);
+ g_assert_cmpuint(retrieved[2], ==, 2);
+
+ memset(retrieved, 0, sizeof(retrieved));
+
+ num_retrieved = gpiod_line_request_get_requested_offsets(request,
+ retrieved, 6);
+
+ g_assert_cmpuint(num_retrieved, ==, 4);
+ g_assert_cmpuint(retrieved[0], ==, 0);
+ g_assert_cmpuint(retrieved[1], ==, 1);
+ g_assert_cmpuint(retrieved[2], ==, 2);
+ g_assert_cmpuint(retrieved[3], ==, 3);
+}
--
2.37.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [libgpiod][PATCH v2 3/8] core: provide gpiod_line_config_set_output_values()
2023-01-20 9:45 [libgpiod][PATCH v2 0/8] treewide: continue beating libgpiod v2 into shape for an upcoming release Bartosz Golaszewski
2023-01-20 9:45 ` [libgpiod][PATCH v2 1/8] README: update for libgpiod v2 Bartosz Golaszewski
2023-01-20 9:45 ` [libgpiod][PATCH v2 2/8] treewide: unify gpiod_line_config/request_get_offsets() functions Bartosz Golaszewski
@ 2023-01-20 9:45 ` Bartosz Golaszewski
2023-01-20 9:45 ` [libgpiod][PATCH v2 4/8] gpioset: use gpiod_line_config_set_output_values() Bartosz Golaszewski
` (4 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Bartosz Golaszewski @ 2023-01-20 9:45 UTC (permalink / raw)
To: Kent Gibson, Linus Walleij, Andy Shevchenko, Viresh Kumar
Cc: linux-gpio, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Currently if user wants to use the same settings for a set of requested
lines with the exception of the output value - they need to go through
hoops by updating the line settings object and adding it one by one to
the line config. Provide a helper function that allows to set a global
list of output values that override the settings. For details on the
interface: see documentation in this commit.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
include/gpiod.h | 25 ++++++++++++++
lib/line-config.c | 60 +++++++++++++++++++++++++++++++---
tests/gpiod-test-helpers.h | 10 ++++++
tests/tests-line-config.c | 67 ++++++++++++++++++++++++++++++++++++++
4 files changed, 158 insertions(+), 4 deletions(-)
diff --git a/include/gpiod.h b/include/gpiod.h
index fea2076..a895dae 100644
--- a/include/gpiod.h
+++ b/include/gpiod.h
@@ -785,6 +785,31 @@ struct gpiod_line_settings *
gpiod_line_config_get_line_settings(struct gpiod_line_config *config,
unsigned int offset);
+/**
+ * @brief Set output values for a number of lines.
+ * @param config Line config object.
+ * @param values Buffer containing the output values.
+ * @param num_values Number of values in the buffer.
+ * @return 0 on success, -1 on error.
+ *
+ * This is a helper that allows users to set multiple (potentially different)
+ * output values at once while using the same line settings object. Instead of
+ * modifying the output value in the settings object and calling
+ * ::gpiod_line_config_add_line_settings multiple times, we can specify the
+ * settings, add them for a set of offsets and then call this function to
+ * set the output values.
+ *
+ * Values set by this function override whatever values were specified in the
+ * regular line settings.
+ *
+ * Each value must be associated with the line identified by the corresponding
+ * entry in the offset array filled by
+ * ::gpiod_line_request_get_requested_offsets.
+ */
+int gpiod_line_config_set_output_values(struct gpiod_line_config *config,
+ const enum gpiod_line_value *values,
+ size_t num_values);
+
/**
* @brief Get the number of configured line offsets.
* @param config Line config object.
diff --git a/lib/line-config.c b/lib/line-config.c
index 877e7ef..fef62de 100644
--- a/lib/line-config.c
+++ b/lib/line-config.c
@@ -25,6 +25,8 @@ struct per_line_config {
struct gpiod_line_config {
struct per_line_config line_configs[LINES_MAX];
size_t num_configs;
+ enum gpiod_line_value output_values[LINES_MAX];
+ size_t num_output_values;
struct settings_node *sref_list;
};
@@ -136,23 +138,60 @@ GPIOD_API struct gpiod_line_settings *
gpiod_line_config_get_line_settings(struct gpiod_line_config *config,
unsigned int offset)
{
+ struct gpiod_line_settings *settings;
struct per_line_config *per_line;
size_t i;
+ int ret;
assert(config);
for (i = 0; i < config->num_configs; i++) {
per_line = &config->line_configs[i];
- if (per_line->offset == offset)
- return gpiod_line_settings_copy(
+ if (per_line->offset == offset) {
+ settings = gpiod_line_settings_copy(
per_line->node->settings);
+ if (!settings)
+ return NULL;
+
+ /*
+ * If a global output value was set for this line - use
+ * it and override the one stored in settings.
+ */
+ if (config->num_output_values > i) {
+ ret = gpiod_line_settings_set_output_value(
+ settings,
+ config->output_values[i]);
+ if (ret) {
+ gpiod_line_settings_free(settings);
+ return NULL;
+ }
+ }
+
+ return settings;
+ }
}
errno = ENOENT;
return NULL;
}
+GPIOD_API int
+gpiod_line_config_set_output_values(struct gpiod_line_config *config,
+ const enum gpiod_line_value *values,
+ size_t num_values)
+{
+ if (num_values > LINES_MAX) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ memcpy(config->output_values, values, num_values * sizeof(*values));
+ config->num_output_values = num_values;
+
+ return 0;
+}
+
GPIOD_API size_t
gpiod_line_config_get_num_configured_offsets(struct gpiod_line_config *config)
{
@@ -206,6 +245,13 @@ static bool has_at_least_one_output_direction(struct gpiod_line_config *config)
return false;
}
+static void set_output_value(uint64_t *vals, size_t bit,
+ enum gpiod_line_value value)
+{
+ gpiod_line_mask_assign_bit(vals, bit,
+ value == GPIOD_LINE_VALUE_ACTIVE ? 1 : 0);
+}
+
static void set_kernel_output_values(uint64_t *mask, uint64_t *vals,
struct gpiod_line_config *config)
{
@@ -227,8 +273,14 @@ static void set_kernel_output_values(uint64_t *mask, uint64_t *vals,
gpiod_line_mask_set_bit(mask, i);
value = gpiod_line_settings_get_output_value(
per_line->node->settings);
- gpiod_line_mask_assign_bit(
- vals, i, value == GPIOD_LINE_VALUE_ACTIVE ? 1 : 0);
+ set_output_value(vals, i, value);
+ }
+
+ /* "Global" output values override the ones from per-line settings. */
+ for (i = 0; i < config->num_output_values; i++) {
+ gpiod_line_mask_set_bit(mask, i);
+ value = config->output_values[i];
+ set_output_value(vals, i, value);
}
}
diff --git a/tests/gpiod-test-helpers.h b/tests/gpiod-test-helpers.h
index fb3fd7d..760949e 100644
--- a/tests/gpiod-test-helpers.h
+++ b/tests/gpiod-test-helpers.h
@@ -136,6 +136,16 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(struct_gpiod_edge_event_buffer,
_settings; \
})
+#define gpiod_test_line_config_set_output_values_or_fail(_line_cfg, _values, \
+ _num_values) \
+ do { \
+ gint _ret = gpiod_line_config_set_output_values(_line_cfg, \
+ _values, \
+ _num_values); \
+ g_assert_cmpint(_ret, ==, 0); \
+ gpiod_test_return_if_failed(); \
+ } while (0)
+
#define gpiod_test_create_request_config_or_fail() \
({ \
struct gpiod_request_config *_config = \
diff --git a/tests/tests-line-config.c b/tests/tests-line-config.c
index a1a587d..78c4d6b 100644
--- a/tests/tests-line-config.c
+++ b/tests/tests-line-config.c
@@ -280,3 +280,70 @@ GPIOD_TEST_CASE(get_more_offsets_than_configured)
g_assert_cmpuint(retrieved[2], ==, 2);
g_assert_cmpuint(retrieved[3], ==, 3);
}
+
+GPIOD_TEST_CASE(set_global_output_values)
+{
+ static const guint offsets[] = { 0, 1, 2, 3 };
+ static const enum gpiod_line_value values[] = {
+ GPIOD_LINE_VALUE_ACTIVE,
+ GPIOD_LINE_VALUE_INACTIVE,
+ GPIOD_LINE_VALUE_ACTIVE,
+ GPIOD_LINE_VALUE_INACTIVE,
+ };
+
+ g_autoptr(GPIOSimChip) sim = g_gpiosim_chip_new("num-lines", 4, NULL);
+ g_autoptr(struct_gpiod_line_settings) settings = NULL;
+ g_autoptr(struct_gpiod_line_config) config = NULL;
+ g_autoptr(struct_gpiod_line_request) request = NULL;
+ g_autoptr(struct_gpiod_chip) chip = NULL;
+
+ chip = gpiod_test_open_chip_or_fail(g_gpiosim_chip_get_dev_path(sim));
+ settings = gpiod_test_create_line_settings_or_fail();
+ config = gpiod_test_create_line_config_or_fail();
+
+ gpiod_line_settings_set_direction(settings,
+ GPIOD_LINE_DIRECTION_OUTPUT);
+ gpiod_test_line_config_add_line_settings_or_fail(config, offsets, 4,
+ settings);
+ gpiod_test_line_config_set_output_values_or_fail(config, values, 4);
+
+ request = gpiod_test_request_lines_or_fail(chip, NULL, config);
+
+ g_assert_cmpint(g_gpiosim_chip_get_value(sim, 0), ==,
+ GPIOD_LINE_VALUE_ACTIVE);
+ g_assert_cmpint(g_gpiosim_chip_get_value(sim, 1), ==,
+ GPIOD_LINE_VALUE_INACTIVE);
+ g_assert_cmpint(g_gpiosim_chip_get_value(sim, 2), ==,
+ GPIOD_LINE_VALUE_ACTIVE);
+ g_assert_cmpint(g_gpiosim_chip_get_value(sim, 3), ==,
+ GPIOD_LINE_VALUE_INACTIVE);
+}
+
+GPIOD_TEST_CASE(read_back_global_output_values)
+{
+ static const guint offsets[] = { 0, 1, 2, 3 };
+ static const enum gpiod_line_value values[] = {
+ GPIOD_LINE_VALUE_ACTIVE,
+ GPIOD_LINE_VALUE_INACTIVE,
+ GPIOD_LINE_VALUE_ACTIVE,
+ GPIOD_LINE_VALUE_INACTIVE,
+ };
+
+ g_autoptr(struct_gpiod_line_settings) settings = NULL;
+ g_autoptr(struct_gpiod_line_settings) retrieved = NULL;
+ g_autoptr(struct_gpiod_line_config) config = NULL;
+
+ settings = gpiod_test_create_line_settings_or_fail();
+ config = gpiod_test_create_line_config_or_fail();
+
+ gpiod_line_settings_set_direction(settings,
+ GPIOD_LINE_DIRECTION_OUTPUT);
+ gpiod_line_settings_set_output_value(settings, GPIOD_LINE_VALUE_ACTIVE);
+ gpiod_test_line_config_add_line_settings_or_fail(config, offsets, 4,
+ settings);
+ gpiod_test_line_config_set_output_values_or_fail(config, values, 4);
+
+ retrieved = gpiod_test_line_config_get_line_settings_or_fail(config, 1);
+ g_assert_cmpint(gpiod_line_settings_get_output_value(retrieved), ==,
+ GPIOD_LINE_VALUE_INACTIVE);
+}
--
2.37.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [libgpiod][PATCH v2 4/8] gpioset: use gpiod_line_config_set_output_values()
2023-01-20 9:45 [libgpiod][PATCH v2 0/8] treewide: continue beating libgpiod v2 into shape for an upcoming release Bartosz Golaszewski
` (2 preceding siblings ...)
2023-01-20 9:45 ` [libgpiod][PATCH v2 3/8] core: provide gpiod_line_config_set_output_values() Bartosz Golaszewski
@ 2023-01-20 9:45 ` Bartosz Golaszewski
2023-01-20 9:45 ` [libgpiod][PATCH v2 5/8] bindings: cxx: add line_config.set_output_values() Bartosz Golaszewski
` (3 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Bartosz Golaszewski @ 2023-01-20 9:45 UTC (permalink / raw)
To: Kent Gibson, Linus Walleij, Andy Shevchenko, Viresh Kumar
Cc: linux-gpio, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Use the new line config function to shrink the gpioset code and drop one
for loop.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
tools/gpioset.c | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/tools/gpioset.c b/tools/gpioset.c
index a871a16..1429d65 100644
--- a/tools/gpioset.c
+++ b/tools/gpioset.c
@@ -870,9 +870,9 @@ int main(int argc, char **argv)
struct gpiod_line_config *line_cfg;
struct line_resolver *resolver;
enum gpiod_line_value *values;
- int i, j, num_lines, ret;
struct gpiod_chip *chip;
unsigned int *offsets;
+ int i, num_lines, ret;
struct config cfg;
char **lines;
@@ -933,15 +933,16 @@ int main(int argc, char **argv)
values);
gpiod_line_config_reset(line_cfg);
- for (j = 0; j < num_lines; j++) {
- gpiod_line_settings_set_output_value(settings,
- values[j]);
-
- ret = gpiod_line_config_add_line_settings(
- line_cfg, &offsets[j], 1, settings);
- if (ret)
- die_perror("unable to add line settings");
- }
+
+ ret = gpiod_line_config_add_line_settings(line_cfg, offsets,
+ num_lines, settings);
+ if (ret)
+ die_perror("unable to add line settings");
+
+ ret = gpiod_line_config_set_output_values(line_cfg,
+ values, num_lines);
+ if (ret)
+ die_perror("unable to set output values");
chip = gpiod_chip_open(resolver->chips[i].path);
if (!chip)
--
2.37.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [libgpiod][PATCH v2 5/8] bindings: cxx: add line_config.set_output_values()
2023-01-20 9:45 [libgpiod][PATCH v2 0/8] treewide: continue beating libgpiod v2 into shape for an upcoming release Bartosz Golaszewski
` (3 preceding siblings ...)
2023-01-20 9:45 ` [libgpiod][PATCH v2 4/8] gpioset: use gpiod_line_config_set_output_values() Bartosz Golaszewski
@ 2023-01-20 9:45 ` Bartosz Golaszewski
2023-01-20 9:45 ` [libgpiod][PATCH v2 6/8] bindings: python: add the output_values argument to Chip.request_lines() Bartosz Golaszewski
` (2 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Bartosz Golaszewski @ 2023-01-20 9:45 UTC (permalink / raw)
To: Kent Gibson, Linus Walleij, Andy Shevchenko, Viresh Kumar
Cc: linux-gpio, Bartosz Golaszewski
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 --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
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [libgpiod][PATCH v2 6/8] bindings: python: add the output_values argument to Chip.request_lines()
2023-01-20 9:45 [libgpiod][PATCH v2 0/8] treewide: continue beating libgpiod v2 into shape for an upcoming release Bartosz Golaszewski
` (4 preceding siblings ...)
2023-01-20 9:45 ` [libgpiod][PATCH v2 5/8] bindings: cxx: add line_config.set_output_values() Bartosz Golaszewski
@ 2023-01-20 9:45 ` Bartosz Golaszewski
2023-01-20 9:45 ` [libgpiod][PATCH v2 7/8] bindings: rust: make mutators return &mut self Bartosz Golaszewski
2023-01-20 9:45 ` [libgpiod][PATCH v2 8/8] bindings: rust: provide line_config.set_output_values() Bartosz Golaszewski
7 siblings, 0 replies; 11+ messages in thread
From: Bartosz Golaszewski @ 2023-01-20 9:45 UTC (permalink / raw)
To: Kent Gibson, Linus Walleij, Andy Shevchenko, Viresh Kumar
Cc: linux-gpio, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Add a new optional argument to Chip.request_lines() called output_values.
It accepts a dictionary of mappings between line names or offsets to the
output values the requested lines should be set to at request-time.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
bindings/python/gpiod/chip.py | 30 ++++++++++
bindings/python/gpiod/ext/line-config.c | 64 +++++++++++++++++++++
bindings/python/tests/tests_line_request.py | 55 ++++++++++++++++++
3 files changed, 149 insertions(+)
diff --git a/bindings/python/gpiod/chip.py b/bindings/python/gpiod/chip.py
index ad2eddd..97ff340 100644
--- a/bindings/python/gpiod/chip.py
+++ b/bindings/python/gpiod/chip.py
@@ -6,10 +6,12 @@ from .chip_info import ChipInfo
from .exception import ChipClosedError
from .info_event import InfoEvent
from .internal import poll_fd
+from .line import Value
from .line_info import LineInfo
from .line_settings import LineSettings, _line_settings_to_ext
from .line_request import LineRequest
from collections import Counter
+from collections.abc import Iterable
from datetime import timedelta
from errno import ENOENT
from select import select
@@ -221,6 +223,7 @@ class Chip:
config: dict[tuple[Union[int, str]], Optional[LineSettings]],
consumer: Optional[str] = None,
event_buffer_size: Optional[int] = None,
+ output_values: Optional[dict[tuple[Union[int, str]], Value]] = None,
) -> LineRequest:
"""
Request a set of lines for exclusive usage.
@@ -234,6 +237,10 @@ class Chip:
Consumer string to use for this request.
event_buffer_size:
Size of the kernel edge event buffer to configure for this request.
+ output_values:
+ Dictionary mapping offsets or names to line.Value. This can be used
+ to set the desired output values globally while reusing LineSettings
+ for more lines.
Returns:
New LineRequest object.
@@ -260,10 +267,20 @@ class Chip:
)
)
+ # If we have global output values - map line names to offsets
+ if output_values:
+ mapped_output_values = {
+ self.line_offset_from_id(line): value
+ for line, value in output_values.items()
+ }
+ else:
+ mapped_output_values = None
+
for lines, settings in config.items():
offsets = list()
name_map = dict()
offset_map = dict()
+ global_output_values = list()
if isinstance(lines, int) or isinstance(lines, str):
lines = (lines,)
@@ -271,6 +288,16 @@ class Chip:
for line in lines:
offset = self.line_offset_from_id(line)
offsets.append(offset)
+
+ # If there's a global output value for this offset, store it in the
+ # list for later.
+ if mapped_output_values:
+ global_output_values.append(
+ mapped_output_values[offset]
+ if offset in mapped_output_values
+ else Value.INACTIVE
+ )
+
if isinstance(line, str):
name_map[line] = offset
offset_map[offset] = line
@@ -279,6 +306,9 @@ class Chip:
offsets, _line_settings_to_ext(settings or LineSettings())
)
+ if len(global_output_values):
+ line_cfg.set_output_values(global_output_values)
+
req_internal = self._chip.request_lines(line_cfg, consumer, event_buffer_size)
request = LineRequest(req_internal)
diff --git a/bindings/python/gpiod/ext/line-config.c b/bindings/python/gpiod/ext/line-config.c
index 173ca6b..0bba112 100644
--- a/bindings/python/gpiod/ext/line-config.c
+++ b/bindings/python/gpiod/ext/line-config.c
@@ -89,12 +89,76 @@ line_config_add_line_settings(line_config_object *self, PyObject *args)
Py_RETURN_NONE;
}
+static PyObject *
+line_config_set_output_values(line_config_object *self, PyObject *args)
+{
+ PyObject *values, *iter, *next, *val_stripped;
+ enum gpiod_line_value *valbuf;
+ Py_ssize_t num_values, pos;
+ int ret;
+
+ values = PyTuple_GetItem(args, 0);
+ if (!values)
+ return NULL;
+
+ num_values = PyObject_Size(values);
+ if (num_values < 0)
+ return NULL;
+
+ valbuf = PyMem_Calloc(num_values, sizeof(*valbuf));
+ if (!valbuf)
+ return PyErr_NoMemory();
+
+ iter = PyObject_GetIter(values);
+ if (!iter) {
+ PyMem_Free(valbuf);
+ return NULL;
+ }
+
+ for (pos = 0;; pos++) {
+ next = PyIter_Next(iter);
+ if (!next) {
+ Py_DECREF(iter);
+ break;
+ }
+
+ val_stripped = PyObject_GetAttrString(next, "value");
+ Py_DECREF(next);
+ if (!val_stripped) {
+ PyMem_Free(valbuf);
+ Py_DECREF(iter);
+ return NULL;
+ }
+
+ valbuf[pos] = PyLong_AsLong(val_stripped);
+ Py_DECREF(val_stripped);
+ if (PyErr_Occurred()) {
+ PyMem_Free(valbuf);
+ Py_DECREF(iter);
+ return NULL;
+ }
+ }
+
+ ret = gpiod_line_config_set_output_values(self->cfg,
+ valbuf, num_values);
+ PyMem_Free(valbuf);
+ if (ret)
+ return Py_gpiod_SetErrFromErrno();
+
+ Py_RETURN_NONE;
+}
+
static PyMethodDef line_config_methods[] = {
{
.ml_name = "add_line_settings",
.ml_meth = (PyCFunction)line_config_add_line_settings,
.ml_flags = METH_VARARGS,
},
+ {
+ .ml_name = "set_output_values",
+ .ml_meth = (PyCFunction)line_config_set_output_values,
+ .ml_flags = METH_VARARGS,
+ },
{ }
};
diff --git a/bindings/python/tests/tests_line_request.py b/bindings/python/tests/tests_line_request.py
index c0ac768..096ec7c 100644
--- a/bindings/python/tests/tests_line_request.py
+++ b/bindings/python/tests/tests_line_request.py
@@ -402,6 +402,61 @@ class LineRequestConsumerString(TestCase):
self.assertEqual(info.consumer, "?")
+class LineRequestSetOutputValues(TestCase):
+ def setUp(self):
+ self.sim = gpiosim.Chip(
+ num_lines=4, line_names={0: "foo", 1: "bar", 2: "baz", 3: "xyz"}
+ )
+
+ def tearDown(self):
+ del self.sim
+
+ def test_request_with_globally_set_output_values(self):
+ with gpiod.request_lines(
+ self.sim.dev_path,
+ config={(0, 1, 2, 3): gpiod.LineSettings(direction=Direction.OUTPUT)},
+ output_values={
+ 0: Value.ACTIVE,
+ 1: Value.INACTIVE,
+ 2: Value.ACTIVE,
+ 3: Value.INACTIVE,
+ },
+ ) as request:
+ self.assertEqual(self.sim.get_value(0), SimVal.ACTIVE)
+ self.assertEqual(self.sim.get_value(1), SimVal.INACTIVE)
+ self.assertEqual(self.sim.get_value(2), SimVal.ACTIVE)
+ self.assertEqual(self.sim.get_value(3), SimVal.INACTIVE)
+
+ def test_request_with_globally_set_output_values_with_mapping(self):
+ with gpiod.request_lines(
+ self.sim.dev_path,
+ config={(0, 1, 2, 3): gpiod.LineSettings(direction=Direction.OUTPUT)},
+ output_values={"baz": Value.ACTIVE, "foo": Value.ACTIVE},
+ ) as request:
+ self.assertEqual(self.sim.get_value(0), SimVal.ACTIVE)
+ self.assertEqual(self.sim.get_value(1), SimVal.INACTIVE)
+ self.assertEqual(self.sim.get_value(2), SimVal.ACTIVE)
+ self.assertEqual(self.sim.get_value(3), SimVal.INACTIVE)
+
+ def test_request_with_globally_set_output_values_bad_mapping(self):
+ with self.assertRaises(FileNotFoundError):
+ with gpiod.request_lines(
+ self.sim.dev_path,
+ config={(0, 1, 2, 3): gpiod.LineSettings(direction=Direction.OUTPUT)},
+ output_values={"foobar": Value.ACTIVE},
+ ) as request:
+ pass
+
+ def test_request_with_globally_set_output_values_bad_offset(self):
+ with self.assertRaises(ValueError):
+ with gpiod.request_lines(
+ self.sim.dev_path,
+ config={(0, 1, 2, 3): gpiod.LineSettings(direction=Direction.OUTPUT)},
+ output_values={5: Value.ACTIVE},
+ ) as request:
+ pass
+
+
class ReconfigureRequestedLines(TestCase):
def setUp(self):
self.sim = gpiosim.Chip(num_lines=8, line_names={3: "foo", 4: "bar", 6: "baz"})
--
2.37.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [libgpiod][PATCH v2 7/8] bindings: rust: make mutators return &mut self
2023-01-20 9:45 [libgpiod][PATCH v2 0/8] treewide: continue beating libgpiod v2 into shape for an upcoming release Bartosz Golaszewski
` (5 preceding siblings ...)
2023-01-20 9:45 ` [libgpiod][PATCH v2 6/8] bindings: python: add the output_values argument to Chip.request_lines() Bartosz Golaszewski
@ 2023-01-20 9:45 ` Bartosz Golaszewski
2023-01-25 9:25 ` Viresh Kumar
2023-01-20 9:45 ` [libgpiod][PATCH v2 8/8] bindings: rust: provide line_config.set_output_values() Bartosz Golaszewski
7 siblings, 1 reply; 11+ messages in thread
From: Bartosz Golaszewski @ 2023-01-20 9:45 UTC (permalink / raw)
To: Kent Gibson, Linus Walleij, Andy Shevchenko, Viresh Kumar
Cc: linux-gpio, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
In C++ bindings we can chain the mutators as they all return a reference
to the object they modify. It's a common practice to allow that in Rust
too so make all mutators that don't already do it return a mutable
reference to self.
It's also logically incorrect to make mutators borrow an immutable
reference to self. Even if that builds - as we're fiddling with C
pointers - it could change in the future. It's fine for getters but
setters should all use mutable references.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
.../rust/libgpiod/examples/gpio_events.rs | 2 +-
.../examples/gpio_threaded_info_events.rs | 6 +-
bindings/rust/libgpiod/examples/gpioget.rs | 4 +-
bindings/rust/libgpiod/examples/gpiomon.rs | 2 +-
bindings/rust/libgpiod/examples/gpioset.rs | 4 +-
bindings/rust/libgpiod/src/line_config.rs | 4 +-
bindings/rust/libgpiod/src/line_request.rs | 16 ++--
bindings/rust/libgpiod/src/request_config.rs | 8 +-
bindings/rust/libgpiod/tests/common/config.rs | 8 +-
bindings/rust/libgpiod/tests/info_event.rs | 6 +-
bindings/rust/libgpiod/tests/line_config.rs | 2 +-
bindings/rust/libgpiod/tests/line_request.rs | 73 ++++++++-----------
.../rust/libgpiod/tests/request_config.rs | 2 +-
13 files changed, 65 insertions(+), 72 deletions(-)
diff --git a/bindings/rust/libgpiod/examples/gpio_events.rs b/bindings/rust/libgpiod/examples/gpio_events.rs
index cbdf1b5..b26c60b 100644
--- a/bindings/rust/libgpiod/examples/gpio_events.rs
+++ b/bindings/rust/libgpiod/examples/gpio_events.rs
@@ -25,7 +25,7 @@ fn main() -> Result<()> {
}
let mut lsettings = line::Settings::new()?;
- let lconfig = line::Config::new()?;
+ let mut lconfig = line::Config::new()?;
let mut offsets = Vec::<Offset>::new();
for arg in &args[2..] {
diff --git a/bindings/rust/libgpiod/examples/gpio_threaded_info_events.rs b/bindings/rust/libgpiod/examples/gpio_threaded_info_events.rs
index 367b2f6..620f4ec 100644
--- a/bindings/rust/libgpiod/examples/gpio_threaded_info_events.rs
+++ b/bindings/rust/libgpiod/examples/gpio_threaded_info_events.rs
@@ -32,12 +32,12 @@ fn request_reconfigure_line(
rx: Receiver<()>,
) {
thread::spawn(move || {
- let lconfig = line::Config::new().unwrap();
+ let mut lconfig = line::Config::new().unwrap();
let lsettings = line::Settings::new().unwrap();
lconfig.add_line_settings(&[offset], lsettings).unwrap();
let rconfig = request::Config::new().unwrap();
- let request = chip
+ let mut request = chip
.lock()
.unwrap()
.request_lines(Some(&rconfig), &lconfig)
@@ -49,7 +49,7 @@ fn request_reconfigure_line(
// Wait for parent to signal
rx.recv().expect("Could not receive from channel");
- let lconfig = line::Config::new().unwrap();
+ let mut lconfig = line::Config::new().unwrap();
let mut lsettings = line::Settings::new().unwrap();
lsettings.set_direction(Direction::Output).unwrap();
lconfig.add_line_settings(&[offset], lsettings).unwrap();
diff --git a/bindings/rust/libgpiod/examples/gpioget.rs b/bindings/rust/libgpiod/examples/gpioget.rs
index 74baf30..a71612b 100644
--- a/bindings/rust/libgpiod/examples/gpioget.rs
+++ b/bindings/rust/libgpiod/examples/gpioget.rs
@@ -20,7 +20,7 @@ fn main() -> Result<()> {
}
let mut lsettings = line::Settings::new()?;
- let lconfig = line::Config::new()?;
+ let mut lconfig = line::Config::new()?;
let mut offsets = Vec::<Offset>::new();
for arg in &args[2..] {
@@ -34,7 +34,7 @@ fn main() -> Result<()> {
let path = format!("/dev/gpiochip{}", args[1]);
let chip = Chip::open(&path)?;
- let rconfig = request::Config::new()?;
+ let mut rconfig = request::Config::new()?;
rconfig.set_consumer(&args[0])?;
let request = chip.request_lines(Some(&rconfig), &lconfig)?;
diff --git a/bindings/rust/libgpiod/examples/gpiomon.rs b/bindings/rust/libgpiod/examples/gpiomon.rs
index a09ddfc..8f2a71a 100644
--- a/bindings/rust/libgpiod/examples/gpiomon.rs
+++ b/bindings/rust/libgpiod/examples/gpiomon.rs
@@ -24,7 +24,7 @@ fn main() -> Result<()> {
}
let mut lsettings = line::Settings::new()?;
- let lconfig = line::Config::new()?;
+ let mut lconfig = line::Config::new()?;
let mut offsets = Vec::<Offset>::new();
for arg in &args[2..] {
diff --git a/bindings/rust/libgpiod/examples/gpioset.rs b/bindings/rust/libgpiod/examples/gpioset.rs
index 6247996..4b43010 100644
--- a/bindings/rust/libgpiod/examples/gpioset.rs
+++ b/bindings/rust/libgpiod/examples/gpioset.rs
@@ -24,7 +24,7 @@ fn main() -> Result<()> {
return Err(Error::InvalidArguments);
}
- let lconfig = line::Config::new()?;
+ let mut lconfig = line::Config::new()?;
for arg in &args[2..] {
let pair: Vec<&str> = arg.split('=').collect();
@@ -51,7 +51,7 @@ fn main() -> Result<()> {
let path = format!("/dev/gpiochip{}", args[1]);
let chip = Chip::open(&path)?;
- let rconfig = request::Config::new()?;
+ let mut rconfig = request::Config::new()?;
rconfig.set_consumer(&args[0])?;
chip.request_lines(Some(&rconfig), &lconfig)?;
diff --git a/bindings/rust/libgpiod/src/line_config.rs b/bindings/rust/libgpiod/src/line_config.rs
index 42dad9f..3f42dad 100644
--- a/bindings/rust/libgpiod/src/line_config.rs
+++ b/bindings/rust/libgpiod/src/line_config.rs
@@ -56,7 +56,7 @@ impl Config {
}
/// Add line settings for a set of offsets.
- pub fn add_line_settings(&self, offsets: &[Offset], settings: Settings) -> Result<()> {
+ pub fn add_line_settings(&mut self, offsets: &[Offset], settings: Settings) -> Result<&mut Self> {
// SAFETY: `gpiod_line_config` is guaranteed to be valid here.
let ret = unsafe {
gpiod::gpiod_line_config_add_line_settings(
@@ -73,7 +73,7 @@ impl Config {
errno::errno(),
))
} else {
- Ok(())
+ Ok(self)
}
}
diff --git a/bindings/rust/libgpiod/src/line_request.rs b/bindings/rust/libgpiod/src/line_request.rs
index 7915924..ff701fb 100644
--- a/bindings/rust/libgpiod/src/line_request.rs
+++ b/bindings/rust/libgpiod/src/line_request.rs
@@ -95,7 +95,7 @@ impl Request {
}
/// Set the value of a single line associated with the request.
- pub fn set_value(&self, offset: Offset, value: Value) -> Result<()> {
+ pub fn set_value(&mut self, offset: Offset, value: Value) -> Result<&mut Self> {
// SAFETY: `gpiod_line_request` is guaranteed to be valid here.
let ret =
unsafe { gpiod::gpiod_line_request_set_value(self.request, offset, value.value()) };
@@ -106,12 +106,12 @@ impl Request {
errno::errno(),
))
} else {
- Ok(())
+ Ok(self)
}
}
/// Set values of a subset of lines associated with the request.
- pub fn set_values_subset(&self, map: ValueMap) -> Result<()> {
+ pub fn set_values_subset(&mut self, map: ValueMap) -> Result<&mut Self> {
let mut offsets = Vec::new();
let mut values = Vec::new();
@@ -136,12 +136,12 @@ impl Request {
errno::errno(),
))
} else {
- Ok(())
+ Ok(self)
}
}
/// Set values of all lines associated with the request.
- pub fn set_values(&self, values: &[Value]) -> Result<()> {
+ pub fn set_values(&mut self, values: &[Value]) -> Result<&mut Self> {
if values.len() != self.num_lines() as usize {
return Err(Error::InvalidArguments);
}
@@ -161,12 +161,12 @@ impl Request {
errno::errno(),
))
} else {
- Ok(())
+ Ok(self)
}
}
/// Update the configuration of lines associated with the line request.
- pub fn reconfigure_lines(&self, lconfig: &line::Config) -> Result<()> {
+ pub fn reconfigure_lines(&mut self, lconfig: &line::Config) -> Result<&mut Self> {
// SAFETY: `gpiod_line_request` is guaranteed to be valid here.
let ret =
unsafe { gpiod::gpiod_line_request_reconfigure_lines(self.request, lconfig.config) };
@@ -177,7 +177,7 @@ impl Request {
errno::errno(),
))
} else {
- Ok(())
+ Ok(self)
}
}
diff --git a/bindings/rust/libgpiod/src/request_config.rs b/bindings/rust/libgpiod/src/request_config.rs
index 9d38548..939838c 100644
--- a/bindings/rust/libgpiod/src/request_config.rs
+++ b/bindings/rust/libgpiod/src/request_config.rs
@@ -40,7 +40,7 @@ impl Config {
///
/// If the consumer string is too long, it will be truncated to the max
/// accepted length.
- pub fn set_consumer(&self, consumer: &str) -> Result<()> {
+ pub fn set_consumer(&mut self, consumer: &str) -> Result<&mut Self> {
let consumer = CString::new(consumer).map_err(|_| Error::InvalidString)?;
// SAFETY: `gpiod_request_config` is guaranteed to be valid here.
@@ -51,7 +51,7 @@ impl Config {
)
}
- Ok(())
+ Ok(self)
}
/// Get the consumer name configured in the request config.
@@ -73,9 +73,11 @@ impl Config {
}
/// Set the size of the kernel event buffer for the request.
- pub fn set_event_buffer_size(&self, size: usize) {
+ pub fn set_event_buffer_size(&mut self, size: usize) -> &mut Self {
// SAFETY: `gpiod_request_config` is guaranteed to be valid here.
unsafe { gpiod::gpiod_request_config_set_event_buffer_size(self.config, size as c_ulong) }
+
+ self
}
/// Get the edge event buffer size setting for the request config.
diff --git a/bindings/rust/libgpiod/tests/common/config.rs b/bindings/rust/libgpiod/tests/common/config.rs
index b838b66..36ccc94 100644
--- a/bindings/rust/libgpiod/tests/common/config.rs
+++ b/bindings/rust/libgpiod/tests/common/config.rs
@@ -43,7 +43,7 @@ impl TestConfig {
}
}
- pub(crate) fn rconfig_set_consumer(&self, consumer: &str) {
+ pub(crate) fn rconfig_set_consumer(&mut self, consumer: &str) {
self.rconfig.set_consumer(consumer).unwrap();
}
@@ -100,7 +100,7 @@ impl TestConfig {
pub(crate) fn lconfig_add_settings(&mut self, offsets: &[Offset]) {
self.lconfig
.add_line_settings(offsets, self.lsettings.take().unwrap())
- .unwrap()
+ .unwrap();
}
pub(crate) fn request_lines(&mut self) -> Result<()> {
@@ -128,8 +128,8 @@ impl TestConfig {
self.lsettings.as_mut().unwrap()
}
- pub(crate) fn request(&self) -> &request::Request {
- self.request.as_ref().unwrap()
+ pub(crate) fn request(&mut self) -> &mut request::Request {
+ self.request.as_mut().unwrap()
}
}
diff --git a/bindings/rust/libgpiod/tests/info_event.rs b/bindings/rust/libgpiod/tests/info_event.rs
index 6bf7a0f..f06dd2d 100644
--- a/bindings/rust/libgpiod/tests/info_event.rs
+++ b/bindings/rust/libgpiod/tests/info_event.rs
@@ -24,12 +24,12 @@ mod info_event {
fn request_reconfigure_line(chip: Arc<Mutex<Chip>>, tx: Sender<()>, rx: Receiver<()>) {
thread::spawn(move || {
- let lconfig1 = line::Config::new().unwrap();
+ let mut lconfig1 = line::Config::new().unwrap();
let lsettings = line::Settings::new().unwrap();
lconfig1.add_line_settings(&[7], lsettings).unwrap();
let rconfig = request::Config::new().unwrap();
- let request = chip
+ let mut request = chip
.lock()
.unwrap()
.request_lines(Some(&rconfig), &lconfig1)
@@ -41,7 +41,7 @@ mod info_event {
// Wait for parent to signal
rx.recv().expect("Could not receive from channel");
- let lconfig2 = line::Config::new().unwrap();
+ let mut lconfig2 = line::Config::new().unwrap();
let mut lsettings = line::Settings::new().unwrap();
lsettings.set_direction(Direction::Output).unwrap();
lconfig2.add_line_settings(&[7], lsettings).unwrap();
diff --git a/bindings/rust/libgpiod/tests/line_config.rs b/bindings/rust/libgpiod/tests/line_config.rs
index 95f2178..92a7af3 100644
--- a/bindings/rust/libgpiod/tests/line_config.rs
+++ b/bindings/rust/libgpiod/tests/line_config.rs
@@ -33,7 +33,7 @@ mod line_config {
.unwrap();
// Add settings for multiple lines
- let lconfig = line::Config::new().unwrap();
+ let mut lconfig = line::Config::new().unwrap();
lconfig.add_line_settings(&[0, 1, 2], lsettings1).unwrap();
lconfig.add_line_settings(&[4, 5], lsettings2).unwrap();
diff --git a/bindings/rust/libgpiod/tests/line_request.rs b/bindings/rust/libgpiod/tests/line_request.rs
index c3fc37b..8ec497f 100644
--- a/bindings/rust/libgpiod/tests/line_request.rs
+++ b/bindings/rust/libgpiod/tests/line_request.rs
@@ -123,7 +123,7 @@ mod line_request {
// Value read properly after reconfigure
let mut lsettings = line::Settings::new().unwrap();
lsettings.set_active_low(true);
- let lconfig = line::Config::new().unwrap();
+ let mut lconfig = line::Config::new().unwrap();
lconfig.add_line_settings(&offsets, lsettings).unwrap();
request.reconfigure_lines(&lconfig).unwrap();
assert_eq!(request.value(7).unwrap(), Value::InActive);
@@ -153,22 +153,21 @@ mod line_request {
config.lconfig_val(Some(Direction::Output), Some(Value::InActive));
config.lconfig_add_settings(&offsets);
config.request_lines().unwrap();
- let request = config.request();
// Set single value
- request.set_value(1, Value::Active).unwrap();
+ config.request().set_value(1, Value::Active).unwrap();
assert_eq!(config.sim_val(0).unwrap(), SimValue::InActive);
assert_eq!(config.sim_val(1).unwrap(), SimValue::Active);
assert_eq!(config.sim_val(3).unwrap(), SimValue::InActive);
assert_eq!(config.sim_val(4).unwrap(), SimValue::InActive);
- request.set_value(1, Value::InActive).unwrap();
+ config.request().set_value(1, Value::InActive).unwrap();
assert_eq!(config.sim_val(1).unwrap(), SimValue::InActive);
// Set values of subset
let mut map = ValueMap::new();
map.insert(4, Value::Active);
map.insert(3, Value::Active);
- request.set_values_subset(map).unwrap();
+ config.request().set_values_subset(map).unwrap();
assert_eq!(config.sim_val(0).unwrap(), SimValue::InActive);
assert_eq!(config.sim_val(1).unwrap(), SimValue::InActive);
assert_eq!(config.sim_val(3).unwrap(), SimValue::Active);
@@ -177,12 +176,12 @@ mod line_request {
let mut map = ValueMap::new();
map.insert(4, Value::InActive);
map.insert(3, Value::InActive);
- request.set_values_subset(map).unwrap();
+ config.request().set_values_subset(map).unwrap();
assert_eq!(config.sim_val(3).unwrap(), SimValue::InActive);
assert_eq!(config.sim_val(4).unwrap(), SimValue::InActive);
// Set all values
- request
+ config.request()
.set_values(&[
Value::Active,
Value::InActive,
@@ -194,7 +193,7 @@ mod line_request {
assert_eq!(config.sim_val(1).unwrap(), SimValue::InActive);
assert_eq!(config.sim_val(3).unwrap(), SimValue::Active);
assert_eq!(config.sim_val(4).unwrap(), SimValue::InActive);
- request
+ config.request()
.set_values(&[
Value::InActive,
Value::InActive,
@@ -251,7 +250,7 @@ mod line_request {
// Reconfigure
let mut lsettings = line::Settings::new().unwrap();
lsettings.set_direction(Direction::Input).unwrap();
- let lconfig = line::Config::new().unwrap();
+ let mut lconfig = line::Config::new().unwrap();
// The uAPI config has only 10 attribute slots, this should pass.
for offset in offsets {
@@ -285,10 +284,8 @@ mod line_request {
let info = config.chip().line_info(0).unwrap();
assert_eq!(info.bias().unwrap(), None);
- let request = config.request();
-
// Reconfigure
- let lconfig = line::Config::new().unwrap();
+ let mut lconfig = line::Config::new().unwrap();
let mut lsettings = line::Settings::new().unwrap();
lsettings
.set_prop(&[
@@ -297,11 +294,11 @@ mod line_request {
])
.unwrap();
lconfig.add_line_settings(&[0], lsettings).unwrap();
- request.reconfigure_lines(&lconfig).unwrap();
+ config.request().reconfigure_lines(&lconfig).unwrap();
let info = config.chip().line_info(0).unwrap();
assert_eq!(info.bias().unwrap(), Some(Bias::PullUp));
- let lconfig = line::Config::new().unwrap();
+ let mut lconfig = line::Config::new().unwrap();
let mut lsettings = line::Settings::new().unwrap();
lsettings
.set_prop(&[
@@ -310,11 +307,11 @@ mod line_request {
])
.unwrap();
lconfig.add_line_settings(&[0], lsettings).unwrap();
- request.reconfigure_lines(&lconfig).unwrap();
+ config.request().reconfigure_lines(&lconfig).unwrap();
let info = config.chip().line_info(0).unwrap();
assert_eq!(info.bias().unwrap(), Some(Bias::PullDown));
- let lconfig = line::Config::new().unwrap();
+ let mut lconfig = line::Config::new().unwrap();
let mut lsettings = line::Settings::new().unwrap();
lsettings
.set_prop(&[
@@ -323,7 +320,7 @@ mod line_request {
])
.unwrap();
lconfig.add_line_settings(&[0], lsettings).unwrap();
- request.reconfigure_lines(&lconfig).unwrap();
+ config.request().reconfigure_lines(&lconfig).unwrap();
let info = config.chip().line_info(0).unwrap();
assert_eq!(info.bias().unwrap(), Some(Bias::Disabled));
}
@@ -336,10 +333,8 @@ mod line_request {
let info = config.chip().line_info(0).unwrap();
assert_eq!(info.drive().unwrap(), Drive::PushPull);
- let request = config.request();
-
// Reconfigure
- let lconfig = line::Config::new().unwrap();
+ let mut lconfig = line::Config::new().unwrap();
let mut lsettings = line::Settings::new().unwrap();
lsettings
.set_prop(&[
@@ -348,11 +343,11 @@ mod line_request {
])
.unwrap();
lconfig.add_line_settings(&[0], lsettings).unwrap();
- request.reconfigure_lines(&lconfig).unwrap();
+ config.request().reconfigure_lines(&lconfig).unwrap();
let info = config.chip().line_info(0).unwrap();
assert_eq!(info.drive().unwrap(), Drive::PushPull);
- let lconfig = line::Config::new().unwrap();
+ let mut lconfig = line::Config::new().unwrap();
let mut lsettings = line::Settings::new().unwrap();
lsettings
.set_prop(&[
@@ -361,11 +356,11 @@ mod line_request {
])
.unwrap();
lconfig.add_line_settings(&[0], lsettings).unwrap();
- request.reconfigure_lines(&lconfig).unwrap();
+ config.request().reconfigure_lines(&lconfig).unwrap();
let info = config.chip().line_info(0).unwrap();
assert_eq!(info.drive().unwrap(), Drive::OpenDrain);
- let lconfig = line::Config::new().unwrap();
+ let mut lconfig = line::Config::new().unwrap();
let mut lsettings = line::Settings::new().unwrap();
lsettings
.set_prop(&[
@@ -374,7 +369,7 @@ mod line_request {
])
.unwrap();
lconfig.add_line_settings(&[0], lsettings).unwrap();
- request.reconfigure_lines(&lconfig).unwrap();
+ config.request().reconfigure_lines(&lconfig).unwrap();
let info = config.chip().line_info(0).unwrap();
assert_eq!(info.drive().unwrap(), Drive::OpenSource);
}
@@ -387,10 +382,8 @@ mod line_request {
let info = config.chip().line_info(0).unwrap();
assert_eq!(info.edge_detection().unwrap(), None);
- let request = config.request();
-
// Reconfigure
- let lconfig = line::Config::new().unwrap();
+ let mut lconfig = line::Config::new().unwrap();
let mut lsettings = line::Settings::new().unwrap();
lsettings
.set_prop(&[
@@ -399,11 +392,11 @@ mod line_request {
])
.unwrap();
lconfig.add_line_settings(&[0], lsettings).unwrap();
- request.reconfigure_lines(&lconfig).unwrap();
+ config.request().reconfigure_lines(&lconfig).unwrap();
let info = config.chip().line_info(0).unwrap();
assert_eq!(info.edge_detection().unwrap(), Some(Edge::Both));
- let lconfig = line::Config::new().unwrap();
+ let mut lconfig = line::Config::new().unwrap();
let mut lsettings = line::Settings::new().unwrap();
lsettings
.set_prop(&[
@@ -412,11 +405,11 @@ mod line_request {
])
.unwrap();
lconfig.add_line_settings(&[0], lsettings).unwrap();
- request.reconfigure_lines(&lconfig).unwrap();
+ config.request().reconfigure_lines(&lconfig).unwrap();
let info = config.chip().line_info(0).unwrap();
assert_eq!(info.edge_detection().unwrap(), Some(Edge::Rising));
- let lconfig = line::Config::new().unwrap();
+ let mut lconfig = line::Config::new().unwrap();
let mut lsettings = line::Settings::new().unwrap();
lsettings
.set_prop(&[
@@ -425,7 +418,7 @@ mod line_request {
])
.unwrap();
lconfig.add_line_settings(&[0], lsettings).unwrap();
- request.reconfigure_lines(&lconfig).unwrap();
+ config.request().reconfigure_lines(&lconfig).unwrap();
let info = config.chip().line_info(0).unwrap();
assert_eq!(info.edge_detection().unwrap(), Some(Edge::Falling));
}
@@ -438,22 +431,20 @@ mod line_request {
let info = config.chip().line_info(0).unwrap();
assert_eq!(info.event_clock().unwrap(), EventClock::Monotonic);
- let request = config.request();
-
// Reconfigure
- let lconfig = line::Config::new().unwrap();
+ let mut lconfig = line::Config::new().unwrap();
let mut lsettings = line::Settings::new().unwrap();
lsettings.set_event_clock(EventClock::Monotonic).unwrap();
lconfig.add_line_settings(&[0], lsettings).unwrap();
- request.reconfigure_lines(&lconfig).unwrap();
+ config.request().reconfigure_lines(&lconfig).unwrap();
let info = config.chip().line_info(0).unwrap();
assert_eq!(info.event_clock().unwrap(), EventClock::Monotonic);
- let lconfig = line::Config::new().unwrap();
+ let mut lconfig = line::Config::new().unwrap();
let mut lsettings = line::Settings::new().unwrap();
lsettings.set_event_clock(EventClock::Realtime).unwrap();
lconfig.add_line_settings(&[0], lsettings).unwrap();
- request.reconfigure_lines(&lconfig).unwrap();
+ config.request().reconfigure_lines(&lconfig).unwrap();
let info = config.chip().line_info(0).unwrap();
assert_eq!(info.event_clock().unwrap(), EventClock::Realtime);
}
@@ -470,7 +461,7 @@ mod line_request {
let request = config.request();
// Reconfigure
- let lconfig = line::Config::new().unwrap();
+ let mut lconfig = line::Config::new().unwrap();
let mut lsettings = line::Settings::new().unwrap();
lsettings.set_event_clock(EventClock::HTE).unwrap();
lconfig.add_line_settings(&[0], lsettings).unwrap();
@@ -491,7 +482,7 @@ mod line_request {
let request = config.request();
// Reconfigure
- let lconfig = line::Config::new().unwrap();
+ let mut lconfig = line::Config::new().unwrap();
let mut lsettings = line::Settings::new().unwrap();
lsettings
.set_prop(&[
diff --git a/bindings/rust/libgpiod/tests/request_config.rs b/bindings/rust/libgpiod/tests/request_config.rs
index 8c67638..d78c4bd 100644
--- a/bindings/rust/libgpiod/tests/request_config.rs
+++ b/bindings/rust/libgpiod/tests/request_config.rs
@@ -27,7 +27,7 @@ mod request_config {
#[test]
fn initialized() {
const CONSUMER: &str = "foobar";
- let rconfig = request::Config::new().unwrap();
+ let mut rconfig = request::Config::new().unwrap();
rconfig.set_consumer(CONSUMER).unwrap();
rconfig.set_event_buffer_size(64);
--
2.37.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [libgpiod][PATCH v2 8/8] bindings: rust: provide line_config.set_output_values()
2023-01-20 9:45 [libgpiod][PATCH v2 0/8] treewide: continue beating libgpiod v2 into shape for an upcoming release Bartosz Golaszewski
` (6 preceding siblings ...)
2023-01-20 9:45 ` [libgpiod][PATCH v2 7/8] bindings: rust: make mutators return &mut self Bartosz Golaszewski
@ 2023-01-20 9:45 ` Bartosz Golaszewski
2023-01-25 9:25 ` Viresh Kumar
7 siblings, 1 reply; 11+ messages in thread
From: Bartosz Golaszewski @ 2023-01-20 9:45 UTC (permalink / raw)
To: Kent Gibson, Linus Walleij, Andy Shevchenko, Viresh Kumar
Cc: linux-gpio, Bartosz Golaszewski
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Add a new function to line config allowing to set a list of output values
for requested lines. This works very similarily to the C++ version of the
new C interface.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
bindings/rust/libgpiod/src/lib.rs | 1 +
bindings/rust/libgpiod/src/line_config.rs | 24 +++++++-
bindings/rust/libgpiod/tests/line_config.rs | 62 +++++++++++++++++++++
3 files changed, 86 insertions(+), 1 deletion(-)
diff --git a/bindings/rust/libgpiod/src/lib.rs b/bindings/rust/libgpiod/src/lib.rs
index a5d018c..f268ceb 100644
--- a/bindings/rust/libgpiod/src/lib.rs
+++ b/bindings/rust/libgpiod/src/lib.rs
@@ -71,6 +71,7 @@ pub enum OperationType {
InfoEventGetLineInfo,
LineConfigNew,
LineConfigAddSettings,
+ LineConfigSetOutputValues,
LineConfigGetOffsets,
LineConfigGetSettings,
LineRequestReconfigLines,
diff --git a/bindings/rust/libgpiod/src/line_config.rs b/bindings/rust/libgpiod/src/line_config.rs
index 3f42dad..32f057f 100644
--- a/bindings/rust/libgpiod/src/line_config.rs
+++ b/bindings/rust/libgpiod/src/line_config.rs
@@ -7,7 +7,7 @@ use std::collections::HashMap;
use super::{
gpiod,
- line::{Offset, Settings},
+ line::{Offset, Settings, Value},
Error, OperationType, Result,
};
@@ -77,6 +77,28 @@ impl Config {
}
}
+ /// Set output values for a number of lines.
+ pub fn set_output_values(&mut self, values: &[Value]) -> Result<&mut Self> {
+ let mut mapped_values = Vec::new();
+ for value in values {
+ mapped_values.push(value.value());
+ }
+
+ let ret = unsafe {
+ gpiod::gpiod_line_config_set_output_values(self.config, mapped_values.as_ptr(),
+ values.len() as u64)
+ };
+
+ if ret == -1 {
+ Err(Error::OperationFailed(
+ OperationType::LineConfigSetOutputValues,
+ errno::errno(),
+ ))
+ } else {
+ Ok(self)
+ }
+ }
+
/// Get a mapping of offsets to line settings stored by this object.
pub fn line_settings(&self) -> Result<HashMap<Offset, Settings>> {
let mut map: HashMap<Offset, Settings> = HashMap::new();
diff --git a/bindings/rust/libgpiod/tests/line_config.rs b/bindings/rust/libgpiod/tests/line_config.rs
index 92a7af3..96ce127 100644
--- a/bindings/rust/libgpiod/tests/line_config.rs
+++ b/bindings/rust/libgpiod/tests/line_config.rs
@@ -5,9 +5,11 @@
mod common;
mod line_config {
+ use libgpiod::chip::Chip;
use libgpiod::line::{
self, Bias, Direction, Drive, Edge, EventClock, SettingKind, SettingVal, Value,
};
+ use gpiosim_sys::Sim;
#[test]
fn settings() {
@@ -76,4 +78,64 @@ mod line_config {
SettingVal::OutputValue(Value::Active)
);
}
+
+ #[test]
+ fn set_global_output_values() {
+ let sim = Sim::new(Some(4), None, true).unwrap();
+ let mut settings = line::Settings::new().unwrap();
+ settings.set_direction(Direction::Output).unwrap();
+
+ let mut config = line::Config::new().unwrap();
+ config
+ .add_line_settings(&[0, 1, 2, 3], settings)
+ .unwrap()
+ .set_output_values(&[
+ Value::Active,
+ Value::InActive,
+ Value::Active,
+ Value::InActive
+ ])
+ .unwrap();
+
+ let chip = Chip::open(&sim.dev_path()).unwrap();
+ let _request = chip.request_lines(None, &config);
+
+ assert_eq!(sim.val(0).unwrap(), gpiosim_sys::Value::Active);
+ assert_eq!(sim.val(1).unwrap(), gpiosim_sys::Value::InActive);
+ assert_eq!(sim.val(2).unwrap(), gpiosim_sys::Value::Active);
+ assert_eq!(sim.val(3).unwrap(), gpiosim_sys::Value::InActive);
+ }
+
+ #[test]
+ fn read_back_global_output_values() {
+ let mut settings = line::Settings::new().unwrap();
+ settings
+ .set_direction(Direction::Output)
+ .unwrap()
+ .set_output_value(Value::Active)
+ .unwrap();
+
+ let mut config = line::Config::new().unwrap();
+ config
+ .add_line_settings(&[0, 1, 2, 3], settings)
+ .unwrap()
+ .set_output_values(&[
+ Value::Active,
+ Value::InActive,
+ Value::Active,
+ Value::InActive,
+ ])
+ .unwrap();
+
+ assert_eq!(
+ config
+ .line_settings()
+ .unwrap()
+ .get(&1)
+ .unwrap()
+ .output_value()
+ .unwrap(),
+ Value::InActive
+ );
+ }
}
--
2.37.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [libgpiod][PATCH v2 7/8] bindings: rust: make mutators return &mut self
2023-01-20 9:45 ` [libgpiod][PATCH v2 7/8] bindings: rust: make mutators return &mut self Bartosz Golaszewski
@ 2023-01-25 9:25 ` Viresh Kumar
0 siblings, 0 replies; 11+ messages in thread
From: Viresh Kumar @ 2023-01-25 9:25 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Kent Gibson, Linus Walleij, Andy Shevchenko, linux-gpio,
Bartosz Golaszewski
On 20-01-23, 10:45, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
>
> In C++ bindings we can chain the mutators as they all return a reference
> to the object they modify. It's a common practice to allow that in Rust
> too so make all mutators that don't already do it return a mutable
> reference to self.
>
> It's also logically incorrect to make mutators borrow an immutable
> reference to self. Even if that builds - as we're fiddling with C
> pointers - it could change in the future. It's fine for getters but
> setters should all use mutable references.
>
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
> ---
> .../rust/libgpiod/examples/gpio_events.rs | 2 +-
> .../examples/gpio_threaded_info_events.rs | 6 +-
> bindings/rust/libgpiod/examples/gpioget.rs | 4 +-
> bindings/rust/libgpiod/examples/gpiomon.rs | 2 +-
> bindings/rust/libgpiod/examples/gpioset.rs | 4 +-
> bindings/rust/libgpiod/src/line_config.rs | 4 +-
> bindings/rust/libgpiod/src/line_request.rs | 16 ++--
> bindings/rust/libgpiod/src/request_config.rs | 8 +-
> bindings/rust/libgpiod/tests/common/config.rs | 8 +-
> bindings/rust/libgpiod/tests/info_event.rs | 6 +-
> bindings/rust/libgpiod/tests/line_config.rs | 2 +-
> bindings/rust/libgpiod/tests/line_request.rs | 73 ++++++++-----------
> .../rust/libgpiod/tests/request_config.rs | 2 +-
> 13 files changed, 65 insertions(+), 72 deletions(-)
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
--
viresh
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [libgpiod][PATCH v2 8/8] bindings: rust: provide line_config.set_output_values()
2023-01-20 9:45 ` [libgpiod][PATCH v2 8/8] bindings: rust: provide line_config.set_output_values() Bartosz Golaszewski
@ 2023-01-25 9:25 ` Viresh Kumar
0 siblings, 0 replies; 11+ messages in thread
From: Viresh Kumar @ 2023-01-25 9:25 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Kent Gibson, Linus Walleij, Andy Shevchenko, linux-gpio,
Bartosz Golaszewski
On 20-01-23, 10:45, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
>
> Add a new function to line config allowing to set a list of output values
> for requested lines. This works very similarily to the C++ version of the
> new C interface.
>
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
> ---
> bindings/rust/libgpiod/src/lib.rs | 1 +
> bindings/rust/libgpiod/src/line_config.rs | 24 +++++++-
> bindings/rust/libgpiod/tests/line_config.rs | 62 +++++++++++++++++++++
> 3 files changed, 86 insertions(+), 1 deletion(-)
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
--
viresh
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2023-01-25 9:25 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-01-20 9:45 [libgpiod][PATCH v2 0/8] treewide: continue beating libgpiod v2 into shape for an upcoming release Bartosz Golaszewski
2023-01-20 9:45 ` [libgpiod][PATCH v2 1/8] README: update for libgpiod v2 Bartosz Golaszewski
2023-01-20 9:45 ` [libgpiod][PATCH v2 2/8] treewide: unify gpiod_line_config/request_get_offsets() functions Bartosz Golaszewski
2023-01-20 9:45 ` [libgpiod][PATCH v2 3/8] core: provide gpiod_line_config_set_output_values() Bartosz Golaszewski
2023-01-20 9:45 ` [libgpiod][PATCH v2 4/8] gpioset: use gpiod_line_config_set_output_values() Bartosz Golaszewski
2023-01-20 9:45 ` [libgpiod][PATCH v2 5/8] bindings: cxx: add line_config.set_output_values() Bartosz Golaszewski
2023-01-20 9:45 ` [libgpiod][PATCH v2 6/8] bindings: python: add the output_values argument to Chip.request_lines() Bartosz Golaszewski
2023-01-20 9:45 ` [libgpiod][PATCH v2 7/8] bindings: rust: make mutators return &mut self Bartosz Golaszewski
2023-01-25 9:25 ` Viresh Kumar
2023-01-20 9:45 ` [libgpiod][PATCH v2 8/8] bindings: rust: provide line_config.set_output_values() Bartosz Golaszewski
2023-01-25 9:25 ` Viresh Kumar
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.