From patchwork Fri Jan 20 09:45:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bartosz Golaszewski X-Patchwork-Id: 645488 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5C3E3C25B50 for ; Fri, 20 Jan 2023 09:45:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229533AbjATJp0 (ORCPT ); Fri, 20 Jan 2023 04:45:26 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37738 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229928AbjATJp0 (ORCPT ); Fri, 20 Jan 2023 04:45:26 -0500 Received: from mail-wm1-x333.google.com (mail-wm1-x333.google.com [IPv6:2a00:1450:4864:20::333]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6DF237AF13 for ; Fri, 20 Jan 2023 01:45:24 -0800 (PST) Received: by mail-wm1-x333.google.com with SMTP id l41-20020a05600c1d2900b003daf986faaeso3215527wms.3 for ; Fri, 20 Jan 2023 01:45:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bgdev-pl.20210112.gappssmtp.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=z5+SW9LTuCmqNqI0GFaxRM/Jn8L/U60QiwU3h3L6sx0=; b=ByzD2BGq0uBG9Ieqmj4I1nCLvrvm/6DHMyScgZY2/RNSvYUDRVkL9YUP5CsyxfQCCv x4GNznjWKM91kFsg88m1uuiW7pAipqOk7yeRYPwAnILVwNSJpUGYCLhKcActqk2L28kO WgnScl9QYvcEfrXXTPNKQKfFjNuMGGl+kqZCrRKZpMkCRskwT/SJH9NKx2SjWIZbhVlS hlgKrjJz0CmBDBT/ZnuDSmruE1W5SspJ/4Nwtxi7n71myAdvZZC7x4a3N1GEkoXNDzmu canuKTWuRvhgJIAKXt7TmespVVjMhVSxfS6uk0rLL8Ra22fXOcrRorwmGPftjaclqYIl vLBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=z5+SW9LTuCmqNqI0GFaxRM/Jn8L/U60QiwU3h3L6sx0=; b=PK1vyny0WYCI1lxIANtfwbuqxb9aNzhHCjPcAU4kMxNi24IywImyjwwqyyKN6p6QoA 4i/Fd7RdSVy94ic0NY8j5xA7ELAqZg+DNFCvzOr7uNlyG6eStK7Ui9GaUuwdLtpsz5vn uyO91240nKggatbgWR90I/CQxypnJffSQBfVd6FuFaEqlEOYhYoaZXumwtfrNX0uGfJ8 TsOogbreh72OaY3lk5ecqHZVWuUqfqAnMRElTKxGol90sjef4t43/GoHqWCTqtiBJzvi ji7ZlS4UwJHRenjLKbS+DF8QB4pY/+gl7xXxI612rFi6CIj1rUve+7xVUxjtsG3ZSuNP 3bkw== X-Gm-Message-State: AFqh2kqKScFRGVvmOUWzRDJWnb+TS6ZbmJ4kQbRB3PIYZg+lzbBacJOo 9Wdqmj4kSVwe5bBMTFvldPG0Zg== X-Google-Smtp-Source: AMrXdXsIrg4FxG22oWxbe/uDx6cB1y9XNKC2QkIpWLVqBvoK4+jZF+J1W8UDmS9hJ2fg4+Wz/I4i7w== X-Received: by 2002:a05:600c:3488:b0:3cf:68f8:790b with SMTP id a8-20020a05600c348800b003cf68f8790bmr9828598wmq.11.1674207922955; Fri, 20 Jan 2023 01:45:22 -0800 (PST) Received: from brgl-uxlite.home ([2a01:cb1d:334:ac00:580c:7b02:3ffd:b2e]) by smtp.gmail.com with ESMTPSA id v17-20020a05600c445100b003d9e74dd9b2sm1800485wmn.9.2023.01.20.01.45.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Jan 2023 01:45:22 -0800 (PST) From: Bartosz Golaszewski To: Kent Gibson , Linus Walleij , Andy Shevchenko , Viresh Kumar Cc: linux-gpio@vger.kernel.org, Bartosz Golaszewski Subject: [libgpiod][PATCH v2 1/8] README: update for libgpiod v2 Date: Fri, 20 Jan 2023 10:45:08 +0100 Message-Id: <20230120094515.40464-2-brgl@bgdev.pl> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20230120094515.40464-1-brgl@bgdev.pl> References: <20230120094515.40464-1-brgl@bgdev.pl> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: Bartosz Golaszewski Certain parts of the README file still refer to concepts removed from libgpiod v2. Update whatever needs updating. Signed-off-by: Bartosz Golaszewski --- 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 +# SPDX-FileCopyrightText: 2017-2023 Bartosz Golaszewski 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. From patchwork Fri Jan 20 09:45:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bartosz Golaszewski X-Patchwork-Id: 645487 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D4216C05027 for ; Fri, 20 Jan 2023 09:45:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230076AbjATJp3 (ORCPT ); Fri, 20 Jan 2023 04:45:29 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37784 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230056AbjATJp2 (ORCPT ); Fri, 20 Jan 2023 04:45:28 -0500 Received: from mail-wm1-x334.google.com (mail-wm1-x334.google.com [IPv6:2a00:1450:4864:20::334]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8D28B7AF17 for ; Fri, 20 Jan 2023 01:45:25 -0800 (PST) Received: by mail-wm1-x334.google.com with SMTP id iv8-20020a05600c548800b003db04a0a46bso838753wmb.0 for ; Fri, 20 Jan 2023 01:45:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bgdev-pl.20210112.gappssmtp.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=2GYuWC7x/KrxABv7fvoKWy6GceB7jmeAzF0teD5zuEo=; b=jsivnWThbar4prSsVwfkvTkzk/GHeWmsjE0oqt7U3rPaOggeaOQ+OCH6xmM+P34vj/ 3sgNfPLy/1ynvNg1xg6b0UTJGwCvJiv5A9Wp5HD6amudL7YZi2WqYqN/7ctndFiAmczF zpUcICWQriwRCMHp2DcJcUi4qIIhsY8VTgo7JoThmo4gkd5YX9jaUvhuNfED0VcWqcVB iP0zpmni1JA6mUP331UW39Uscvw9xU3xo4jJj3oaAeDC/PQQER1kdE40QJ4Vs7t6OMqf SrpIiUpKZG3IkhpLlqgH35fMK5YguBghsLjKCEbaNFo3Re8GIBrd18GTLlPS2Ph4gy31 rlhA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=2GYuWC7x/KrxABv7fvoKWy6GceB7jmeAzF0teD5zuEo=; b=ltDoyZ419iY39NVeFEkysllgfoBl98yZ+gS0PgACr7HdxSL6ucA6vR27BLC9itnu1Z 8rulYeWwq78KrAyBEKYYGX+kR5ykg81QCfxeI6isLPcO1yrmsp4nomB656q0gSUbPUrd +db/YQtSzLinYO+cGZHPlPGihjCVyvTwcwWEfgnnhtYxWvmmPXAetlsZFwIvhTvLpJP1 FG0SHf0OF9FrnOVMX6Y+RrycWJlInFZZuMkVT/LYVSYrW+C13mDLkpS4x6sqAn81Uz/S KAmwNrLJKPs2rzw70NGUhNl3Q8m7gIjDss0t9ri/VK0kKgPmxZ/AHvbaxjXK+sroTSQY FNcA== X-Gm-Message-State: AFqh2kojAQLKehkJOuPKAapovcrzK92zLv/9aVfqwzA7Fo8/39EbOGge bzHqyw2OqkLh33iIoVCfhC+z/Q== X-Google-Smtp-Source: AMrXdXstaMQ4bQ2/4qVH9JI5q+gI1mi5JWYz13WNcQ6ygdbc4Ogp6q5GOjWQd2Tg8N8feXQaDJho6w== X-Received: by 2002:a05:600c:600e:b0:3c6:e62e:2e74 with SMTP id az14-20020a05600c600e00b003c6e62e2e74mr9783240wmb.15.1674207923894; Fri, 20 Jan 2023 01:45:23 -0800 (PST) Received: from brgl-uxlite.home ([2a01:cb1d:334:ac00:580c:7b02:3ffd:b2e]) by smtp.gmail.com with ESMTPSA id v17-20020a05600c445100b003d9e74dd9b2sm1800485wmn.9.2023.01.20.01.45.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Jan 2023 01:45:23 -0800 (PST) From: Bartosz Golaszewski To: Kent Gibson , Linus Walleij , Andy Shevchenko , Viresh Kumar Cc: linux-gpio@vger.kernel.org, Bartosz Golaszewski Subject: [libgpiod][PATCH v2 2/8] treewide: unify gpiod_line_config/request_get_offsets() functions Date: Fri, 20 Jan 2023 10:45:09 +0100 Message-Id: <20230120094515.40464-3-brgl@bgdev.pl> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20230120094515.40464-1-brgl@bgdev.pl> References: <20230120094515.40464-1-brgl@bgdev.pl> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: Bartosz Golaszewski 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 --- 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_config::get_line_settings() const { + ::std::size_t num_offsets = ::gpiod_line_config_get_num_configured_offsets( + this->_m_priv->config.get()); ::std::map 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 offsets(num_offsets); if (num_offsets == 0) return settings_map; - ::std::unique_ptr 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 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 -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 { - // 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> { + let mut map: HashMap = 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> { - 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 #include #include +#include #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 #include #include +#include #include #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); +} From patchwork Fri Jan 20 09:45:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bartosz Golaszewski X-Patchwork-Id: 644741 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 45D9AC25B4E for ; Fri, 20 Jan 2023 09:45:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230053AbjATJp2 (ORCPT ); Fri, 20 Jan 2023 04:45:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37770 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229624AbjATJp1 (ORCPT ); Fri, 20 Jan 2023 04:45:27 -0500 Received: from mail-wm1-x336.google.com (mail-wm1-x336.google.com [IPv6:2a00:1450:4864:20::336]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3A9167AF19 for ; Fri, 20 Jan 2023 01:45:26 -0800 (PST) Received: by mail-wm1-x336.google.com with SMTP id f19-20020a1c6a13000000b003db0ef4dedcso5407099wmc.4 for ; Fri, 20 Jan 2023 01:45:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bgdev-pl.20210112.gappssmtp.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=GbwaYrtx3NfHAMCcGzfdHbsuKlNjskyOHHyz7pViyMc=; b=dfA8ZtMpzZG0AOi7dMrKBPJ7wZaDCm1/IQWelxOUc3AKPBRAKrHX8fdovYxVMWNs9R grSUANHt0EyYpZS96u8EMpHeKGJEJqXA4UquqcRko3x/6oOxGQjPCkTUPh4sJlrppwxV oDJza9AFmKf0eDgrLwu/TNwZCF8T1nj0xRrkz7RzH8QhgMsc+77psXtLCjvwTBvzUV/F 1P7VBCd85uEIBgrbaOaYSI+4nFRuV1M+XMvNEYUFAyDQRQ3wU8Q/o9NmWeWlZhTs/JQe a/yPqCcq23B5eDC7PZ0EchsXOrBCoATTl4HGN/Sh082+EZAaxy0vpeOvlEAQxblZSe8T SN9g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=GbwaYrtx3NfHAMCcGzfdHbsuKlNjskyOHHyz7pViyMc=; b=1tJQ4KW7xXKNn6+hfN433hahcHOn3we0g4a6c9oDPZVl7/4EdlurPtSderJ2qXP9Jm CoHzygBWkgfV/hjv2MXXii73EEQKml2M0CiuOMbFrI5gXp+siTN1UJ24ktVSTNY5QxZZ TjjatxojGHF7Uk3DpXiXo9gwViZJEXFo7AnCvgujLC0Zb9ATTOsP9aTMqDRL0wPMCGI4 +4UcVcJ1m4DFioewEDqhufTEa0fFNyALx3kp1LPoPB24M9CQLcJSzMrUXRsej7yNfjhB f1axhfFRuw/p7QlcozyiEkO1Ns32R2wNWpDMCbSJshmNeen7b0quAawo4YkloKql3KJw /9yw== X-Gm-Message-State: AFqh2kr8Ry2CIWEGZyKHIhDcsURyc2MjWDZ974WW73zX7+XkUz/0+hF9 h/fbbWQbpBu3R9Aa+N6tBd0XlbI0ahlfr8+5 X-Google-Smtp-Source: AMrXdXtOK4cHW0Nt3RZx6Al9rcXr/MGiyyIFGYNrT0LwYiAB3/lwD2wcFUVtUgg1whhSkld2nK7qKw== X-Received: by 2002:a05:600c:35ce:b0:3db:1caf:1020 with SMTP id r14-20020a05600c35ce00b003db1caf1020mr6625256wmq.35.1674207924674; Fri, 20 Jan 2023 01:45:24 -0800 (PST) Received: from brgl-uxlite.home ([2a01:cb1d:334:ac00:580c:7b02:3ffd:b2e]) by smtp.gmail.com with ESMTPSA id v17-20020a05600c445100b003d9e74dd9b2sm1800485wmn.9.2023.01.20.01.45.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Jan 2023 01:45:24 -0800 (PST) From: Bartosz Golaszewski To: Kent Gibson , Linus Walleij , Andy Shevchenko , Viresh Kumar Cc: linux-gpio@vger.kernel.org, Bartosz Golaszewski Subject: [libgpiod][PATCH v2 3/8] core: provide gpiod_line_config_set_output_values() Date: Fri, 20 Jan 2023 10:45:10 +0100 Message-Id: <20230120094515.40464-4-brgl@bgdev.pl> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20230120094515.40464-1-brgl@bgdev.pl> References: <20230120094515.40464-1-brgl@bgdev.pl> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: Bartosz Golaszewski 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 --- 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); +} From patchwork Fri Jan 20 09:45:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bartosz Golaszewski X-Patchwork-Id: 644742 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 09866C27C76 for ; Fri, 20 Jan 2023 09:45:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229928AbjATJp1 (ORCPT ); Fri, 20 Jan 2023 04:45:27 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37752 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229624AbjATJp0 (ORCPT ); Fri, 20 Jan 2023 04:45:26 -0500 Received: from mail-wm1-x32f.google.com (mail-wm1-x32f.google.com [IPv6:2a00:1450:4864:20::32f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DDD657AF0B for ; Fri, 20 Jan 2023 01:45:25 -0800 (PST) Received: by mail-wm1-x32f.google.com with SMTP id c10-20020a05600c0a4a00b003db0636ff84so3238173wmq.0 for ; Fri, 20 Jan 2023 01:45:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bgdev-pl.20210112.gappssmtp.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=QqYkAVDDJHqckoBGfhi4xsYYLbZddtA7wLw1qqPJGNc=; b=fISfqToLdi2KsdJevtG0TxCiHuprHieWJwPsyciUAouZKO8TZG27n9D/yLLZAUT9uw VvDWmGN84dDgZ8qNNkRc54SWP3zzXhjg+21UBDKGKqWk/z+zbmvS2L4kExPxDml3I1/Y PApCz3GgjoY7AHdCu7fieapAg9mpJWRzSbJr2fRvxsQuJXlGs1ug63FsiUVg4URgO5yt q74Ryg4AhAR/pGBoBO7XWM3JMAjD7RRJWwu+/GLxrRw0PCQpxqFw/ZldFZVk/pZX02Om jDf7Y9/RDYMr9og3HcaVNxr6DqSVDUePh6lWS0SmHJYQEvkzlVGI+3HR4jo6A+r7a3U7 kZ4Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=QqYkAVDDJHqckoBGfhi4xsYYLbZddtA7wLw1qqPJGNc=; b=ub4opv+3Lw3s93Iw6RxMmeuN/AJEtPC0fHO095vyNyjF+J2wCTaCOJx8eu5T1XBV/X OnSHsWgBqrBHJjZSLuccBcVzsHH3oG4yQxyNhqvXoHlRM2ZJkq2MyPZAHXIMZpXW9bTQ e77cFtVD7GlGufyQ7A37dt0Co9komt5tV4CbVNVnf0vwKzvWvpxgTSCR5lzpP73T+E+r uRVyx9G8gAmRr1HY7hMxQlwz8eP3EWAm2QnrdofvItgGYebtTJpRtn2gQgTXw1rLtGcc Kpm9gslw39wqgQ+3zGL3aEoPMbstZ4Rad5XAyR3HtMWYfo3waR2hlWplWUUIvJ/BN/iK +p3w== X-Gm-Message-State: AFqh2kpzSFFCkMD6lbPdEwgNXWTC2XFzW2KcblYikgCFlS9SFC9BIhQJ YZnS3yOErCCr6RFceeeWGHm8+tYYeeo0MNSv X-Google-Smtp-Source: AMrXdXuct8PIJR/hayrQfsHjYIDoSQBQqgerheEd9FYQ3rQNeAf19NmffoYaOToP+2Aknzp/iJcfMw== X-Received: by 2002:a05:600c:538e:b0:3da:516:19ed with SMTP id hg14-20020a05600c538e00b003da051619edmr13339214wmb.29.1674207925469; Fri, 20 Jan 2023 01:45:25 -0800 (PST) Received: from brgl-uxlite.home ([2a01:cb1d:334:ac00:580c:7b02:3ffd:b2e]) by smtp.gmail.com with ESMTPSA id v17-20020a05600c445100b003d9e74dd9b2sm1800485wmn.9.2023.01.20.01.45.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Jan 2023 01:45:25 -0800 (PST) From: Bartosz Golaszewski To: Kent Gibson , Linus Walleij , Andy Shevchenko , Viresh Kumar Cc: linux-gpio@vger.kernel.org, Bartosz Golaszewski Subject: [libgpiod][PATCH v2 4/8] gpioset: use gpiod_line_config_set_output_values() Date: Fri, 20 Jan 2023 10:45:11 +0100 Message-Id: <20230120094515.40464-5-brgl@bgdev.pl> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20230120094515.40464-1-brgl@bgdev.pl> References: <20230120094515.40464-1-brgl@bgdev.pl> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: Bartosz Golaszewski Use the new line config function to shrink the gpioset code and drop one for loop. Signed-off-by: Bartosz Golaszewski --- 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) From patchwork Fri Jan 20 09:45:12 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bartosz Golaszewski X-Patchwork-Id: 644740 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2DD9AC25B4E for ; Fri, 20 Jan 2023 09:45:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230058AbjATJpa (ORCPT ); Fri, 20 Jan 2023 04:45:30 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37792 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229624AbjATJp3 (ORCPT ); Fri, 20 Jan 2023 04:45:29 -0500 Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [IPv6:2a00:1450:4864:20::329]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D69E07AF20 for ; Fri, 20 Jan 2023 01:45:27 -0800 (PST) Received: by mail-wm1-x329.google.com with SMTP id o17-20020a05600c511100b003db021ef437so3206363wms.4 for ; Fri, 20 Jan 2023 01:45:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bgdev-pl.20210112.gappssmtp.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=WgI3Fk/2gyiGGUplRcEoLYgVoGEyCL5gPGqpn2TaikQ=; b=zUP8VBb5cmOSIL81LjrNf895TysTZxzc5GgqOmP4eG4Utp3rSfES5HNZIa0s1ZaJ98 PzN28NtVK6jR0JrJcM05CiUarLHU+r4raM0WA+UG++B7UpBmZj/MMk4TTF6ADbmULTPS aNnGkz0DgEB8m9ds7ssEf81qC+nCzF18h5MtTlyBEsNUkCAeyvdTZA8ZkcBzgobbZN7i TQcfcVAf2MJpZQ7ESwF2ym+DmUfiWiFlWHjTm/9W4FHOi1H8jFdIpo9SFWO32nqaOpF3 3RUneWBL8xN6nDELWkqvZLES3/fl8KD/PSOpbTAsWvsKx+b8S9aUSA9cYfD62Nk5lmp3 g/SA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=WgI3Fk/2gyiGGUplRcEoLYgVoGEyCL5gPGqpn2TaikQ=; b=GtLrdG3YxYz88yOMspp85kdsKJCEtPHDZqOhYb3C+sbIrY6Lou0R8LWQaOUcC2RdHQ BbRGM0MerZkPq49hYmuIwMM+ADb6JyufYVLe7c1LzATaJasKM8KJQSlO2yxMAEbblh04 xWdASAHBpKmwW5kHkLAO8Y4KW1xCT0fFMlopTio90u0xWhvcs/HYeGy60rRZ7GpsfP5v ThK8YwNwhYDvn5SqEOgrb+Mldbh5Nb2NG04dCp2SzOvC/h67oM2OBhT3w2yKUpQZajF+ FRrzFBmiEGSD7iyWJrEshcIMKyRSSC8uXCuQ4mWvbdVSfRzn3znI9ZlmfE2Jmwm9qWw6 aKNQ== X-Gm-Message-State: AFqh2kp6ED0wZAJEfHeyWvJVlUVCxCKYL3TdpyFooTlaRWBjl7oDxJLL C28oWdHgN/GoZ1n7h7IMfF8gMg== X-Google-Smtp-Source: AMrXdXue0oH8uHP2vxwMu5rH2Fp8f1Y6PsyNEWKDEENGbkPocJHI3TyBLsedSKglLLRlXfNbxJWLEQ== X-Received: by 2002:a05:600c:3b07:b0:3d1:cdf7:debf with SMTP id m7-20020a05600c3b0700b003d1cdf7debfmr12893471wms.26.1674207926441; Fri, 20 Jan 2023 01:45:26 -0800 (PST) Received: from brgl-uxlite.home ([2a01:cb1d:334:ac00:580c:7b02:3ffd:b2e]) by smtp.gmail.com with ESMTPSA id v17-20020a05600c445100b003d9e74dd9b2sm1800485wmn.9.2023.01.20.01.45.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Jan 2023 01:45:25 -0800 (PST) From: Bartosz Golaszewski To: Kent Gibson , Linus Walleij , Andy Shevchenko , Viresh Kumar Cc: linux-gpio@vger.kernel.org, Bartosz Golaszewski Subject: [libgpiod][PATCH v2 5/8] bindings: cxx: add line_config.set_output_values() Date: Fri, 20 Jan 2023 10:45:12 +0100 Message-Id: <20230120094515.40464-6-brgl@bgdev.pl> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20230120094515.40464-1-brgl@bgdev.pl> References: <20230120094515.40464-1-brgl@bgdev.pl> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: Bartosz Golaszewski 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 --- 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 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_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 #include +#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; From patchwork Fri Jan 20 09:45:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bartosz Golaszewski X-Patchwork-Id: 645486 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 22843C05027 for ; Fri, 20 Jan 2023 09:45:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229624AbjATJpc (ORCPT ); Fri, 20 Jan 2023 04:45:32 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37828 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230084AbjATJpa (ORCPT ); Fri, 20 Jan 2023 04:45:30 -0500 Received: from mail-wm1-x336.google.com (mail-wm1-x336.google.com [IPv6:2a00:1450:4864:20::336]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EB3987AF17 for ; Fri, 20 Jan 2023 01:45:28 -0800 (PST) Received: by mail-wm1-x336.google.com with SMTP id g10so3558091wmo.1 for ; Fri, 20 Jan 2023 01:45:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bgdev-pl.20210112.gappssmtp.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=MR2dqVhDh+olCelVxo17uAA/Tk7kYBlUgOIr5XZX4lY=; b=d/comnS2vUtn4st9RD+u3lzpxXk6Ne3Ntz5MyRQQH7g7HaeIJqoPwgo5TCexoUuM4W fIHRh4/aDbD60Vs17NVJ//ckoGeQu0A1/91KoalfpwjkQhNSvwlIznooH8rzHzgWnq8j uyploFzFsmCHkU+AQGAhji1uWU3xfvdAML+9lOo5Zjw0v5gMLsEhW7qUJ93L8DKJAMFa Nd3QlRNBvSqkwJnRVJRU3QUjhu7PzWrD1h8Iv++T2w9x9OGrpVZBNqDFw1WFwgsuTYTD 0pR5AgP3QKbSaIlzYTS1qBNeyOJcFv7ExRftRKiAJvaknieBEq+boN0W6taoeKI0K6rR ZbyQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=MR2dqVhDh+olCelVxo17uAA/Tk7kYBlUgOIr5XZX4lY=; b=eVOBB5nsJPL8TbjYCtxcWFxeQ+xdifF21BG40BXUpIUnz+ZL3OkHAWcp4yXRI0dO2w ALa678apM2Vwuxffy6s9ngUjkkWO1ZvPkRTZOqE5LT29cKOOsBKlh/92BBZsnyG2qOR1 Y7z6SdoPGYEubo4hr3muXXZUdmCMTD+Xk8yZEIUXnDgzpXag3R1rasMuqM5t1urSmzk6 vYd8KuiUNKpvNYH2XfChHTaDE+rLtoRbE6uNx7aBQsti41pksbYyk15ggM9lu0nneS0g hhv18M5eLN+AORj+2BNwWRj6lOfNfzr4sbnuJyBNnZq16kgfMReh2mHeUsyW3Qgu0b0/ hX9A== X-Gm-Message-State: AFqh2koGt3KgMaVi/EnVMl0A06CevOnkTJTyH+Ttx/d1FbqUTrfA8et+ 3OFDa0GQU4A9fDaaxQHbhe2AFA== X-Google-Smtp-Source: AMrXdXtzqG3L5LBXmcpFuG+fDJxr4Rgr8gz0+mQTr2CN0Pca9H359K/QFnYPZce1iDwofgpPL1amJw== X-Received: by 2002:a05:600c:4e08:b0:3db:1a41:663a with SMTP id b8-20020a05600c4e0800b003db1a41663amr7567434wmq.20.1674207927451; Fri, 20 Jan 2023 01:45:27 -0800 (PST) Received: from brgl-uxlite.home ([2a01:cb1d:334:ac00:580c:7b02:3ffd:b2e]) by smtp.gmail.com with ESMTPSA id v17-20020a05600c445100b003d9e74dd9b2sm1800485wmn.9.2023.01.20.01.45.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Jan 2023 01:45:27 -0800 (PST) From: Bartosz Golaszewski To: Kent Gibson , Linus Walleij , Andy Shevchenko , Viresh Kumar Cc: linux-gpio@vger.kernel.org, Bartosz Golaszewski Subject: [libgpiod][PATCH v2 6/8] bindings: python: add the output_values argument to Chip.request_lines() Date: Fri, 20 Jan 2023 10:45:13 +0100 Message-Id: <20230120094515.40464-7-brgl@bgdev.pl> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20230120094515.40464-1-brgl@bgdev.pl> References: <20230120094515.40464-1-brgl@bgdev.pl> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: Bartosz Golaszewski 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 --- 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"}) From patchwork Fri Jan 20 09:45:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bartosz Golaszewski X-Patchwork-Id: 645485 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 01A3BC27C7C for ; Fri, 20 Jan 2023 09:45:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229902AbjATJpe (ORCPT ); Fri, 20 Jan 2023 04:45:34 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37850 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230095AbjATJpc (ORCPT ); Fri, 20 Jan 2023 04:45:32 -0500 Received: from mail-wm1-x332.google.com (mail-wm1-x332.google.com [IPv6:2a00:1450:4864:20::332]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0476F7AF20 for ; Fri, 20 Jan 2023 01:45:29 -0800 (PST) Received: by mail-wm1-x332.google.com with SMTP id e19-20020a05600c439300b003db1cac0c1fso3926238wmn.5 for ; Fri, 20 Jan 2023 01:45:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bgdev-pl.20210112.gappssmtp.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=BJP2lJ4UKFavY1ic4B59VsaKuHhjsUyjQZE8rnzk8Ig=; b=swXWxnolHIgNgV5LnVUrn94sCxaWSBz6YgGscmKgns1J7BjO1Nqff5bH4BumC9VK5S OTrJjgAT2OT+IeowDHb1DMMfC26p9ySXq5IWD1oBBjRB8uyp4nxvZu/59e/L9qHSDknr gHCCyeauY5dZQVkIXdQmil0EHa8GauD4W2AZQxkYmYblOJFGcI+p97mnykEphmwX9sxi P5Hf5eTNOanf6RZu8Yl4WqKYS/FV0eaRUBbfF2YAjLRnVGoRQKdvpAvJgA1hXhpYm1d6 unUtZkFIVHYC0XVlczfNwwDwZdNkcFz4w4qH8IkBYVmDcFkE9pw9d14BhoAh/+7dpP0y RY1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=BJP2lJ4UKFavY1ic4B59VsaKuHhjsUyjQZE8rnzk8Ig=; b=lOQNgRM5jvxxfED5OMR+3MhcLcuLg/Uw2Prh5KlXKzG2qYpF9+yzOd/wz1t+r/d/N5 CUJQHzNieoK+pFdHzKGZ5pd5+5uTg6Xtqq/CkSnyYYc8eyWz1C2vE9tTMG0YU2zm8cbL lIPxCVub9oqTjKFFiulq82JSF37SYHVvG5yTvB/nK862XGNgaikQIkjBu6taikinN8/Y 6ttkydanspM2eHvMBE+Gw13AkYgDYrTUkn84alAzadzBjx7llfzZbgOwj+HQXmpSOUSq vpqNlwEBuJsOaAOms3OfPNEW5z5svjRXTEaw+O/ndoktFK7zdtLWJBLNz1uadBPRrO7S 2XrQ== X-Gm-Message-State: AFqh2koWmz9DrT1cREYu/ToPPzsdBvKWnDrkaU/OMmEd1i3DH/G/s/KZ M0gUtF/OsQEevNVVJLm/yVMPNQ== X-Google-Smtp-Source: AMrXdXscEA6RE47sitsCXCtgiR7VfmSOJ1ePk7MZ4ESP3/Gr62FpeyM+mU0LsWe5dnBLe3HkuRAo1A== X-Received: by 2002:a05:600c:2116:b0:3d6:10e:68a8 with SMTP id u22-20020a05600c211600b003d6010e68a8mr9735980wml.0.1674207928381; Fri, 20 Jan 2023 01:45:28 -0800 (PST) Received: from brgl-uxlite.home ([2a01:cb1d:334:ac00:580c:7b02:3ffd:b2e]) by smtp.gmail.com with ESMTPSA id v17-20020a05600c445100b003d9e74dd9b2sm1800485wmn.9.2023.01.20.01.45.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Jan 2023 01:45:28 -0800 (PST) From: Bartosz Golaszewski To: Kent Gibson , Linus Walleij , Andy Shevchenko , Viresh Kumar Cc: linux-gpio@vger.kernel.org, Bartosz Golaszewski Subject: [libgpiod][PATCH v2 7/8] bindings: rust: make mutators return &mut self Date: Fri, 20 Jan 2023 10:45:14 +0100 Message-Id: <20230120094515.40464-8-brgl@bgdev.pl> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20230120094515.40464-1-brgl@bgdev.pl> References: <20230120094515.40464-1-brgl@bgdev.pl> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: Bartosz Golaszewski 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 Acked-by: Viresh Kumar --- .../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::::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::::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::::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>, 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); From patchwork Fri Jan 20 09:45:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bartosz Golaszewski X-Patchwork-Id: 644739 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9B3D2C27C76 for ; Fri, 20 Jan 2023 09:45:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230084AbjATJpd (ORCPT ); Fri, 20 Jan 2023 04:45:33 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37830 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230092AbjATJpa (ORCPT ); Fri, 20 Jan 2023 04:45:30 -0500 Received: from mail-wm1-x333.google.com (mail-wm1-x333.google.com [IPv6:2a00:1450:4864:20::333]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A529A7AF28 for ; Fri, 20 Jan 2023 01:45:29 -0800 (PST) Received: by mail-wm1-x333.google.com with SMTP id l41-20020a05600c1d2900b003daf986faaeso3215739wms.3 for ; Fri, 20 Jan 2023 01:45:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bgdev-pl.20210112.gappssmtp.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=2E17aiASFSVSKOKEmVb0OD2JLFjLlsJTHoTLVMO3XhM=; b=VTCBM7SXesl2cA9ZxrOMxD70F20bo37Ws0kI3xmm78rJ7eGW4l4M8Q1caM8IKVUgP3 7+QPObrq5EGeAubZpWFC3JjeE1kfDiHcphuRQP0xs3Zw43PEIbtUE1z8VH3wHXX52gNV yNsYm8fdayc62ZAbXEbvCei/C9MU0WBcTaTPhRCmyvz33Y9c26OjZgjeOujom/qvn7Q/ QvG7qVHM8v1IyrPkL9d/kPMxUae5PFPTPpWg3eW9I9ghAb1cGWiAu21u6GOKdrshMvnC daThZbOUn59iSHpe+3WqFT6nsWWu3CV9ySuNubLND0WVY6fDidVY6k78pSzAnUzwZ+cL 5G8w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=2E17aiASFSVSKOKEmVb0OD2JLFjLlsJTHoTLVMO3XhM=; b=b8Ts4ahcOP0FqV+MFg83m9+YCaxmdVVGP5e0Y7rA1NIdcb/ZkaQKdXuW7Gk5QMHD8O QQckFeoLE3HgpKP5PxfjRXlvgEDeRYLrSP1Z24QVpl161NTURLTvtubvKVOzwaqhDDEY dLGRG+idm1EQz6yk5rElZibvmced+YeJiVwIueP1gsyXRjGePS5xD+PeKuSk0o4Pu/fX o9z/ciXhM2hY86FWGksKxHSglRsj6mqk5SFUl7Yrue8uamJDtab3Seuu/pTLjWSfME7r dPxtmjlvzr9sr7U+PIUi7U+hkBDpErJpXbNo+whZNWJQ10XvRV3du0GLIRLVC+mzvc2f Ledg== X-Gm-Message-State: AFqh2kqSYbmPy4aRBtYT+22NpSDMLyPLvTOpJbWEvtthpdQjD2v1h4wv DESBbYWsKUSuRNDnj5/YoIu3B8P5EJtvLeJC X-Google-Smtp-Source: AMrXdXvJzrFWlqCY/PsW4v5t/cEirUiUw7PVs9FBOZ/8gANLjdyO1iWJh7N5lg7qngI5ylCNt1X7lg== X-Received: by 2002:a05:600c:3488:b0:3d2:370b:97f4 with SMTP id a8-20020a05600c348800b003d2370b97f4mr21916048wmq.16.1674207929189; Fri, 20 Jan 2023 01:45:29 -0800 (PST) Received: from brgl-uxlite.home ([2a01:cb1d:334:ac00:580c:7b02:3ffd:b2e]) by smtp.gmail.com with ESMTPSA id v17-20020a05600c445100b003d9e74dd9b2sm1800485wmn.9.2023.01.20.01.45.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Jan 2023 01:45:28 -0800 (PST) From: Bartosz Golaszewski To: Kent Gibson , Linus Walleij , Andy Shevchenko , Viresh Kumar Cc: linux-gpio@vger.kernel.org, Bartosz Golaszewski Subject: [libgpiod][PATCH v2 8/8] bindings: rust: provide line_config.set_output_values() Date: Fri, 20 Jan 2023 10:45:15 +0100 Message-Id: <20230120094515.40464-9-brgl@bgdev.pl> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20230120094515.40464-1-brgl@bgdev.pl> References: <20230120094515.40464-1-brgl@bgdev.pl> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: Bartosz Golaszewski 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 --- 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> { let mut map: HashMap = 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 + ); + } }