Kent Gibson [Wed, 22 May 2024 00:46:42 +0000 (08:46 +0800)]
bindings: python: tests: add test for casting line.Value to bool
The line.Value represents the logical line state, so intuitively you
would expect it to be able to be cast to bool, with ACTIVE
corresponding to True, and INACTIVE to False.
TODO: add a task for migrating C++ tests to Catch2 v3
Current Catch2 release is v3.6. C++ tests in libgpiod still use v2.x.
Catch2 v2 and v3 are not compatible and the tests must be migrated to
the most recent major release. Add a task for it to TODO.
Kent Gibson [Mon, 13 May 2024 16:00:31 +0000 (00:00 +0800)]
tests: add enable_debounce_then_edge_detection
A bug was recently discovered in the kernel that can result in the edge
event fifo not being correctly initialised and stack contents being
returned in edge events. The trigger for the bug is requesting a line with
debounce, but not edge detection, and then reconfiguring the line to
enable edge detection.
Add a test case that triggers the bug. This will fail on kernels that
do not contain the fix for the bug. The test is located in a new test
file, tests-kernel-uapi.c, intended to contain tests specifically
testing some aspect of the kernel uAPI, not libgpiod itself.
tools: tests: accept the new gpio-sim label format in test cases
Since kernel commit 840a97e2fbaf ("gpio: sim: delimit the fwnode name
with a ":" when generating labels") the gpio-sim automatic labels are
generated by delimiting the device name and the fwnode name with ':'
instead of '-' for better readability. This will break the tests once
linux v6.9 is out. Act in advance and accept both forms.
We currently store time as microseconds in 32-bit integers and allow
seconds as the longest time unit when parsing command-line arguments
limiting the time period possible to specify when passing arguments such
as --hold-period to 35 minutes. Let's use 64-bit integers to vastly
increase that.
Use nanosleep() instead of usleep() to extend the possible sleep time
range.
tools: use ppoll() where higher timeout resolution makes sense
We allow timeout units to be specified in microseconds but for poll() we
need to round them up to milliseconds. Switch to ppoll() to avoid losing
precision.
licensing: relicense C++ bindings under LGPL-2.1-or-later
Commit ea84f882d5d3 ("licensing: relicense C++ library code under
LGPL-3.0-or-later") changed the license of C++ bindings in order to
solve potential issues with code generated from templates[1], default
implementations, etc. However this change makes the bindings less
attractive to projects that have strict licensing restrictions and avoid
GPL-3.0 code[2].
After talking to Grant Likely I decided that the best approach is to
make the bindings available under LGPL-v2.1-or-later and simply let the
end user decide which version's text to apply.
While at it: tweak the README to also mention that examples are provided
under GPL-2.0-or-later.
Link: [1] https://www.spinics.net/lists/linux-gpio/msg46605.html
Link: [2] https://github.com/brgl/libgpiod/issues/72 Suggested-by: Walter Lozano <walter.lozano@collabora.com> Suggested-by: Grant Likely <grant.likely@linaro.org> Acked-by: Kent Gibson <warthog618@gmail.com> Acked-by: Kevin Hilman <khilman@baylibre.com> Acked-by: Grant Likely <grant.likely@linaro.org> Link: https://lore.kernel.org/r/20240416212141.6683-2-brgl@bgdev.pl Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
build: fix configure error messages on missing functions
Fix three incorrect messages that report missing library functions as
required to build the core library when they are actually needed to build
the gpio-tools.
Fixes: 9e69d7552cf2 ("configure: improve the header and library function checks") Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
README: remove out-of-date information on python bindings
The way Python bindings are built has changed and the information in the
README file is now outdated. Remove the no longer valid bits and - while
at it - point the readers to sub-READMEs for Python and Rust bindings.
orbea [Wed, 20 Mar 2024 13:49:57 +0000 (06:49 -0700)]
bindings: cxx: link using the libtool archives
When linking with internal dependencies that were built with libtool the
most reliable method is to use the libtool archive (.la) files.
When building with slibtool it fails when it doesn't find the -lgpiod
linker flag, but if libgpiod is already installed to the system it will
be built using the system version instead of the newly built libraries.
Link: https://bugs.gentoo.org/913899 Signed-off-by: orbea <orbea@riseup.net>
[Bartosz: fix a typo in tests Makefile] Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
The __repr__() function should - if possible - return a valid Python
expression that can be used to instantiate a new object when evaluated.
LineSettings.__repr__() is missing comas between arguments. Both Chip and
LineSettings also don't prefix the returned string with 'gpiod.'. Fix
both functions and add more test cases - including actually using the
strings returned by __repr__() to create new objects and compare their
contents.
Reported-by: Robert Thomas <rob.thomas@raspberrypi.com> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
core: check for positive values returned by calls to ioctl()
If the kernel GPIO driver (erroneously) returns a positive value from one
of its callbacks, it may end up being propagated to user space as
a positive value returned by the call to ioctl(). Let's treat all
non-zero values as errors as GPIO uAPI ioctl()s are not expected to ever
return positive values.
To that end let's create a wrapper around the libc's ioctl() that checks
the return value and sets errno to EBADE (Invalid exchange) if it's
greater than 0.
This should be addressed in the kernel but will remain a problem on older
or unpatched versions so we need to sanitize it in user-space too.
Reported-by: José Guilherme de Castro Rodrigues <joseguilhermebh@hotmail.com> Fixes: b7ba732e6a93 ("treewide: libgpiod v2 implementation") Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> Reviewed-by: Kent Gibson <warthog618@gmail.com>
The github page over at https://github.com/brgl/libgpiod has been reopened
for bug reports and discussions. Add a link and a mention to the README
file.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> Reviewed-by: Erik Schilling <erik.schilling@linaro.org>
bindings: python: fix package installation with Makefile build
The modules are installed in the .egg directory, and therefore cannot be
imported after that. Additionally PIP tries to remove the global gpiod
module if it's not invoked with the --ignore-installed option.
Specify correct --root and fix the --prefix switch.
core: remove buggy flags sanitization from line-config
We try to drop potentially set output flags from line config if edge
detection is enabled but we use the library enum instead of the one from
the uAPI. In any case, we should actually loudly complain if user tries
to use the output mode with edge-detection (like we do currently) so just
remove offending lines entirely.
Reported-by: Anne Bezemer <j.a.bezemer@opensourcepartners.nl> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> Reviewed-by: Kent Gibson <warthog618@gmail.com> Reviewed-by: Anne Bezemer <j.a.bezemer@opensourcepartners.nl>
Kent Gibson [Fri, 29 Dec 2023 09:33:27 +0000 (17:33 +0800)]
gpioset: reword note on post-exit behaviour
The note regarding the state of a line after gpioset exits is confusing
and unhelpful to the average reader, if not outright incorrect.
A common mis-interpretation is that this behaviour is arbitrarily chosen
by spiteful implementors. The note also specifies that the line reverts
to default, but that is not always the case, or is at least out of the
control of gpioset or libgpiod.
Reword the note to constrain the scope to that relevant to the likely
reader, and to emphasize that the behaviour is inherent in the kernel
GPIO interface, not in the gpioset implementation.
Signed-off-by: Kent Gibson <warthog618@gmail.com> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Erik Schilling [Tue, 21 Nov 2023 08:43:03 +0000 (09:43 +0100)]
bindings: rust: libgpiod-sys: new release
During 86860fb ("bindings: rust: libgpiod: release 0.2.2"), I forgot that
we also need a libgpiod-sys release in order to expose the new feature
flag to raise the minimum libgpiod version.
Changelog:
7552e5d (bindings: rust: expose v2.1 features as flag, 2023-11-06) bc91656 (bindings: rust: add wrapper.h to EXTRA_DIST, 2023-11-03) 2e6ee87 (bindings: rust: mention the libgpiod crate from libgpiod-sys, 2023-07-03) d04639d (bindings: rust: bump MSRV to 1.60, 2023-06-16) ebfed6c (bindings: rust: document build without install, 2023-06-12) bce8623 (bindings: rust: exclude Makefile.am from package, 2023-06-12) caabf53 (bindings: rust: add missing license and copyright boilerplate, 2023-06-13)
Most changes only touch the build scripts or modify packaging details.
Bumping the MSRV and introducing a new feature does not require a major
bump.
Phil Howard [Wed, 8 Nov 2023 15:52:00 +0000 (15:52 +0000)]
bindings: python: standalone build tooling for tests
Move extension definitions and tooling for building tests into
`build_tests.py` and update Makefile.am to call it with appropriate path
prefixes.
`build_tests.py` will perform a standalone build of the text extensions,
keeping any build noise in a temporary directory and copying the final
built modules automatically out to `tests/gpiosim` and `tests/procname`.
Add "python-tests-run" to Makefile.am so it's clear how to run the tests.
Add .so object files generated by build_test.py to Makefile.am's
clean-local.
Signed-off-by: Phil Howard <phil@gadgetoid.com> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Phil Howard [Wed, 25 Oct 2023 08:27:07 +0000 (09:27 +0100)]
bindings: python: optionally include module in sdist
Optionally vendor libgpiod source into sdist so that the Python module can
be built from source, even with a missing or mismatched system libgpiod.
Add two new environment variables "LINK_SYSTEM_LIBGPIOD" and
"LIBGPIOD_VERSION" to control what kind of package setup.py will build.
In order to build an sdist or wheel package with a vendored libgpiod a
version must be specified via the "LIBGPIOD_VERSION" environment variable.
This will instruct setup.py to verify the given version against the list
in sha256sums.asc and ensure it meets or exceeds a LIBGPIOD_MINIMUM_VERSION
required for compatibility with the bindings.
It will then fetch the tarball matching the requested version from
mirrors.edge.kernel.org, verify the sha256 signature, unpack it, and copy
the lib and include directories into the package root so they can be
included in sdist or used to build a binary wheel.
eg: LIBGPIOD_VERSION=2.1.0 python3 setup.py sdist
Will build a source distribution with gpiod version 2.1.0 source included.
It will also save the gpiod version into "libgpiod-version.txt" so that it
can be passed to the build when the sdist is built by pip.
Requiring an explicit version ensures that the Python bindings - which
can be changed and versions independent of libgpiod - are built against a
stable libgpiod release.
In order to force a package with vendored gpiod source to link the system
libgpiod, the "LINK_SYSTEM_LIBGPIOD" environment variable can be used:
eg: LINK_SYSTEM_LIBGPIOD=1 pip install libgpiod
Signed-off-by: Phil Howard <phil@gadgetoid.com> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Erik Schilling [Tue, 10 Oct 2023 07:13:11 +0000 (09:13 +0200)]
bindings: rust: libgpiod: release 0.2.1
While the release technically removes a function, that function was not
available in any released libgpiod version. Therefore, this only bumps
the minor.
This release fixes building with releases from the 2.x series of the C
lib.
bindings: python: replace PyModule_AddObjectRef() with PyModule_AddObject()
PyModule_AddObjectRef() was added in cpython v3.10 while libgpiod claims
to depend on python v3.9. Replace it with an older variant that steals the
reference to the added object on success.
Reported-by: Phil Howard <phil@gadgetoid.com> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Erik Schilling [Fri, 6 Oct 2023 07:24:26 +0000 (09:24 +0200)]
bindings: rust: feature gate unreleased features
`gpiod_line_request_get_chip_name()` is not released yet. Still, libgpiod-sys
will just happily generate bindings for it if it sees the definition in the
header file.
This guards the unreleased features behind an optional feature `vnext`.
To sketch the process of what happens once these features get into an
assumed "2.1" release:
libgpiod-sys will get updated with a `v2_1` feature. That feature would
then raise the minimum version that is attempted to query from pkg-
config. An identical feature will then be introduced on the `libgpiod`
crate and `vnext` guards will be changed to `v2_1` guards. The `vnext`
feature will then be updated to require the new `v2_1` feature.
Eventually, we will probably raise the minimum supported version for the
rust bindings and drop all the version gates before that.
While one would usually use the ToOwned [1] contract in rust, libgpipd's
API only allows copying that may fail.
Thus, we cannot implement the existing trait and roll our own method. I
went with `try_clone` since that seems to be used in similar cases across
the `std` crate [2].
It also closes the gap of not having any way to clone owned instances.
Though - again - not through the Clone trait which may not fail [3].
Erik Schilling [Tue, 3 Oct 2023 09:39:57 +0000 (11:39 +0200)]
bindings: rust: fix soundness of line_info modeling
While attention was provided to prevent freeing in non-owned use-cases,
the lifetime of these object was not properly modeled.
The line_info from an event may only be used for as long as the event
exists.
This allowed us to write unsafe-free Rust code that causes a
use-after-free:
let event = chip.read_info_event().unwrap();
let line_info = event.line_info().unwrap();
drop(event);
dbg!(line_info.name().unwrap());
Which makes the AddressSanitizer scream:
==90154==ERROR: AddressSanitizer: heap-use-after-free on address 0x50b000005dc4 at pc 0x55a4f883a009 bp 0x7f60ac8fbbc0 sp 0x7f60ac8fb388
READ of size 2 at 0x50b000005dc4 thread T2
[...]
#3 0x55a4f8c3d5f3 in libgpiod::line_info::Info::name::h5ba0bfd360ecb405 libgpiod/bindings/rust/libgpiod/src/line_info.rs:70:18
[...]
0x50b000005dc4 is located 4 bytes inside of 112-byte region [0x50b000005dc0,0x50b000005e30)
freed by thread T2 here:
[...]
#1 0x7f60b07f7e31 in gpiod_info_event_free libgpiod/lib/info-event.c:61:2
[...]
previously allocated by thread T2 here:
#0 0x55a4f88b04be in malloc /rustc/llvm/src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:69:3
#1 0x7f60b07f8ff0 in gpiod_line_info_from_uapi libgpiod/lib/line-info.c:144:9
The fix is to distinguish between the owned and non-owned variants and
assigning lifetimes to non-owned variants.
For modeling the non-owned type there are a couple of options. The ideal
solution would be using extern_types [1]. But that is still unstable.
Instead, we are defining a #[repr(transparent)] wrapper around the opaque
gpiod_line_info struct and cast the pointer to a reference.
This was recommended on the Rust Discord server as good practise.
(Thanks to Kyuuhachi, shepmaster, pie_flavor and ilyvion! Also thanks to
@epilys for a brainstorming on this on #linaro-virtualization IRC).
Of course, determining the lifetimes and casting across the types
requires some care. So this adds a couple of SAFETY comments that would
probably also have helped the existing code.
Erik Schilling [Thu, 28 Sep 2023 14:37:30 +0000 (16:37 +0200)]
bindings: rust: mark all owning types as `Send`
The thread-safety rules of libgpiod allow individual object instances to
be used from different threads. So far, this was not actually possible
with the Rust bindings. Not being `Send` disallowed the user to transfer
the ownership to different threads.
Rust also has a `Sync` marker. That one would even allow sending
references of objects to other threads. Since we wrap a lot of C
functions with `fn foo(&self)` signatures, that would not be safe.
libgpiod does not allow concurrent API calls to the same object instance
- which Rust would allow for read-only references. Thus, we do not
define that one.
Chip was already modeled correctly.
line::Info is not marked as Send since it may either be owning or non-
owning. That problem is fixed as part of a separate pull request [1].
Erik Schilling [Thu, 28 Sep 2023 14:37:28 +0000 (16:37 +0200)]
doc: drop unneeded <p> tags
Even before Doxygen gained Markdown support, empty lines were considered
as paragraphs. Changelogs indicate that this was the case since at least
the doxygen 1.2 series (where I found a mentiond that something around
this behaviour was fixed). So at least works in Doxygen versions
released after 2001 [1].
Erik Schilling [Wed, 27 Sep 2023 09:25:24 +0000 (11:25 +0200)]
bindings: rust: drop unneeded Arc within Chip
Chip was modeled with an Arc that only was used to pass the chip pointer
to the chip::Info constructor. With that refactored to take a reference,
we can just drop the Arc.
This allows to get rid of the `Internal` helper struct that was only
required by the Arc.
As a side-effect, we also get rid of this clippy warning:
warning: usage of an `Arc` that is not `Send` or `Sync`
--> libgpiod/src/chip.rs:75:21
|
75 | let ichip = Arc::new(Internal::open(path)?);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the trait `Send` is not implemented for `Internal`
= note: the trait `Sync` is not implemented for `Internal`
= note: required for `Arc<Internal>` to implement `Send` and `Sync`
= help: consider using an `Rc` instead or wrapping the inner type with a `Mutex`
Erik Schilling [Thu, 28 Sep 2023 06:23:19 +0000 (08:23 +0200)]
bindings: rust: remove useless clone
Reported by 1.74.0-nightly:
warning: call to `.clone()` on a reference in this situation does nothing
--> libgpiod/tests/line_request.rs:71:44
|
71 | let chip_name = sim.chip_name().clone();
| ^^^^^^^^ help: remove this redundant call
|
= note: the type `str` does not implement `Clone`, so calling `clone` on `&str` copies the reference, which does not do anything and can be removed
= note: `#[warn(noop_method_call)]` on by default
bindings: python: tests: don't use the same chip from different threads
There are no thread-safety guarantees in libgpiod. Let's not reuse the
chip object created in one thread to generate info events in another but
use a global request function instead.
Reported-by: Erik Schilling <erik.schilling@linaro.org> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> Reviewed-by: Erik Schilling <erik.schilling@linaro.org>
bindings: cxx: tests: don't use the same chip from different threads
There are no thread-safety guarantees in libgpiod. Let's not reuse the
chip object created in one thread to generate info events in another but
create a second chip for that purpose instead.
Reported-by: Erik Schilling <erik.schilling@linaro.org> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> Reviewed-by: Erik Schilling <erik.schilling@linaro.org>
tests: don't use the same chip object from different threads
There are no thread-safety guarantees in libgpiod. Let's not reuse the
chip object created in one thread to generate info events in another but
create a second chip for that purpose instead.
Reported-by: Erik Schilling <erik.schilling@linaro.org> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> Reviewed-by: Erik Schilling <erik.schilling@linaro.org>
While we can get the list of requested offsets from a line-request object,
this information lacks context if we don't provide any data about the GPIO
chip the request was made on. Add a helper allowing users to get the name
of the parent chip.
Erik Schilling [Mon, 3 Jul 2023 07:19:59 +0000 (09:19 +0200)]
bindings: rust: add README.md for libgpiod crate
crates.io treats the README as landing page for a crate [1]. Since
we have none, it currently displays a blank page. Lets add at least a
little bit of info here so people can figure out what they are dealing
with.
For any given target (let's say foobar), automake defaults to looking for
foobar.c if foobar_SOURCES are not specified. Remove redundant assignments
as we've seen multiple hidden typos in makefiles already.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> Reviewed-by: Kent Gibson <warthog618@gmail.com>
bindings: cxx: use () instead of (void) in line_settings::reset()
While () and (void) are synonymous in C++, we use () everywhere else so
fix the only exception. This DOES NOT change the ABI as the generated
symbol is the same (at least as verified on gcc and clang).
Erik Schilling [Mon, 26 Jun 2023 13:14:29 +0000 (15:14 +0200)]
gpiosim: fix data race that corrupts heap
Hit this while seeing some heap corruptions when running cargo test on
the Rust bindings.
Took a bit to track down since I first used address sanitizers, but with
the thread sanitizer it becomes obvious immediately (output simplified):
==================
WARNING: ThreadSanitizer: data race (pid=288119)
Write of size 8 at 0x0000018f1e78 by thread T6:
#0 id_free /libgpiod/tests/gpiosim/gpiosim.c:141:17
#1 dev_release /libgpiod/tests/gpiosim/gpiosim.c:600:2
#2 refcount_dec /libgpiod/tests/gpiosim/gpiosim.c:176:3
#3 gpiosim_dev_unref /libgpiod/tests/gpiosim/gpiosim.c:671:2
#4 bank_release /libgpiod/tests/gpiosim/gpiosim.c:873:2
#5 refcount_dec /libgpiod/tests/gpiosim/gpiosim.c:176:3
#6 gpiosim_bank_unref /libgpiod/tests/gpiosim/gpiosim.c:941:2
[...]
Previous write of size 8 at 0x0000018f1e78 by thread T1:
#0 id_free /libgpiod/tests/gpiosim/gpiosim.c:141:17
#1 bank_release /libgpiod/tests/gpiosim/gpiosim.c:878:2
#2 refcount_dec /libgpiod/tests/gpiosim/gpiosim.c:176:3
#3 gpiosim_bank_unref /libgpiod/tests/gpiosim/gpiosim.c:941:2
[...]
Location is global 'id_del_ctx' of size 16 at 0x0000018f1e70
Thread T6 'chip::verify::f' (tid=288126, running) created by main thread at:
#7 test::run_tests::hd53a07a011bd771f /.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/test/src/lib.rs:407:21
[...]
Thread T1 'chip::open::gpi' (tid=288121, finished) created by main thread at:
#7 test::run_tests::hd53a07a011bd771f /.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/test/src/lib.rs:407:21
[...]
SUMMARY: ThreadSanitizer: data race /libgpiod/tests/gpiosim/gpiosim.c:141:17 in id_free
==================
This eventually can either lead to leaks or double free's that corrupt
the heap and lead to crashes.
The issue got introduced when a previously local variable that did not
require protection was turned into a global variable.
Fixes: 5e111df2fca5 ("gpiosim: use twalk() instead of twalk_r()") Signed-off-by: Erik Schilling <erik.schilling@linaro.org> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Kent Gibson [Fri, 23 Jun 2023 04:39:01 +0000 (12:39 +0800)]
bindings: rust: examples: replace tools examples with use case examples
Replace tool examples with use case examples drawn from the tools,
gpio_events example with buffered_event_lifetimes, and
gpio_threaded_info_events with reconfigure_input_to_output.
Signed-off-by: Kent Gibson <warthog618@gmail.com> Reviewed-by: Erik Schilling <erik.schilling@linaro.org> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Kent Gibson [Fri, 23 Jun 2023 04:39:00 +0000 (12:39 +0800)]
bindings: rust: examples: consistency cleanup
A collection of minor changes to be more consistent with other examples:
- capitalize comments
- add line offset to value outputs
- drop comma from edge event outputs
Signed-off-by: Kent Gibson <warthog618@gmail.com> Reviewed-by: Erik Schilling <erik.schilling@linaro.org> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Kent Gibson [Fri, 23 Jun 2023 04:38:58 +0000 (12:38 +0800)]
bindings: python: examples: consistency cleanup
A collection of minor changes to be more consistent with other examples:
- capitalize comments
- add line offset to value outputs
- drop comma from edge event outputs
- improve behaviour if run on a platform that does not match the
example configuration
- use with to cleanup request in toggle_line_value.py
Signed-off-by: Kent Gibson <warthog618@gmail.com> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>