core: provide gpiod_line_config_set_output_values()
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.
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.
The rust crates builds fine when built with the 'make' command, as
static linking works fine. But when referenced from a remote rust crate,
it gives following error:
error: could not find native static library `gpiod`, perhaps an -L flag is missing?
This happens since we only support 'static' LIB-KIND currently. Remove
the same to allow others to work too.
bindings: rust: make request_config optional in Chip.request_lines()
Request config is not necessary to request lines. In C API we accept
a NULL pointer, in C++ it's not necessary to assign a request_config
to the request builder, in Python the consumer and event buffer size
arguments are optional. Let's make rust bindings consistent and not
require the request config to be always present. Convert the argument
in request_lines to Option and update the rest of the code.
We're using testing wrong variables in the reset_config test case. We
should be checking the retrieved0 settings which are read back from
the line config object.
Implement the copy operator for line_settings. We have a copy() method
for line settings in C API while in C++ it's useful to copy line_settings
returned in an std::map from line_config.get_line_settings().
Makefile.am delegates the build of the python extension to its
setup.py file, which references the extension .c files relative to the
source dir. This makes it impossible to build in a directory that is
different from the source directory (for example, for PC and ARM but
from the same source).
* Invoke setup.py from $(srcdir)
* Modify setup.py to pick up .c files relative from setup.py's own
directory.
Currently we almost never check the validity of pointers passed to the
core C API routines. While we cannot know if a non-NULL pointer points
to an actual object, we can at least verify that it is not NULL before
dereferencing it.
Conceptually we can think of two categories of pointers in libgpiod:
First, there are the objects we manipulate using the API. These are
normally the first arguments in any given method and they are only
instantiated inside the library and never dereferenced by the user.
They should always be valid, so passing a NULL pointer here should
always lead to a crash. Currently it will take the form of a segfault
at the moment of dereference but with this change, we make the user
program abort() with the stack trace pointing right at the offender.
The second category would be pointers to objects that are logically
parameters of methods i.e. not their first argument. Example is:
gpiod_chip_request_lines(chip, req_cfg, line_cfg) (whose logical OOP
version would be: chip->request_lines(req_cfg, line_cfg)). Here we
accept a NULL req_cfg but we'll segfault on a NULL line_cfg. For
consistency: don't crash here but instead return -1 and set errno
to EINVAL. Same everywhere else.
gpiosim: fix error reporting in gpiosim_bank_hog_line()
We don't return errno numbers from public functions - we set errno and
indicate an error by returning -1 or NULL depending on the function
signature. Make gpiosim_bank_hog_line() consistent with that behavior.
configure: restore AS_IF() when using PKG_CHECK_MODULES()
pkg-config fails if we only try to build the tests without building the
tools. I'm not sure why that happens and can't find any other fix than
restore the AS_IF() for the 'with_tools' block.
Surprisingly: PKG_CHECK_MODULES() works fine elsewhere. Add a FIXME in
the configure.ac and investigate later.
Fixes: 68dd8c6e5edb ("configure: drop AS_IF() macros") Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
core: rename gpiod_version_string() to gpiod_api_version()
Instead of telling the user what type this function returns (they can
check it by looking at the prototype), tell them what the return value
actually represents.
configure: improve the header and library function checks
The project is often cross-compiled for embedded systems with all kinds
of wonky toolchains so update configure.ac with checks for less standard
functions and headers. While at it: rearrange the existing checks a bit
so that we only check for headers and symbols when we need them for
current build configuration.
build: use LIBEDIT_CFLAGS when building gpioset with interactive mode
The Makefile doesn't include the libedit CLFLAGS when building gpioset
with interactive mode enabled. This can lead to a build failure if the
header is not in the standard location (/usr/include/editline/readline.h).
AS_IF() is much less readable than a regular if/else and it's only called
for by docs if the code inside the expansion uses AC_REQUIRE(). Convert
AS_IF() occurrences to standard if/else syntax.
The fcntl.h header is needed for openat() and mkdirat() that the gpiosim
code uses. It seems to be pulled in indirectly on most toolchains but for
the sake of correctness, include it explicitly.
treewide: add missing commas to enums and struct definitions
The code is not consistent with regard to following the last element in
enums and struct definitions with a comma. Unless the last element is
guaranteed not to change (e.g. '{ }', or NULL), follow it with a comma
treewide to avoid churn in git when adding new values.
When we run the test suite by calling the __main__ function of the module,
the name of the process as visible in the system becomes "python". Let's
set it to "python-gpiod" before running the tests. This way gpiosim will
name its configfs attributes appropriately.
program_invocation_short_name is set once at the program's start. If we
change the process name using prctl(), we need to retrieve it using the
same system call as program_invocation_short_name will not be updated.
If we set the number of lines to x, set line names or hogs for lines
from 0 through x, then set the number of lines to (x - y), we will not
unlink all the line directories as we only iterate up to num_lines in
bank_release().
Allocate a small structure for every line we create a lineX directory
for and iterate over it in bank_release() to know exactly which ones
need freeing.
bindings: python: decouple the version of the bindings from libgpiod API version
Python bindings now have their own setup.py script and can be built
separately from the rest of the code-base. Let's decouple the python
package version from libgpiod API (but let's keep a module attribute
containing the API version) by introducing a version.py submodule that
can be executed by the setup.py script. This way we have a single
canonical place defining the version number.
While we use it for edge event timestamps exclusively at the moment,
the actual enum names shouldn't limit its application and simply just
refer to existing clock types known by the GPIO uAPI. The relevant
functions are still called set/get_event_clock() as it's in line with
their functionality.
treewide: use plural 'events' in read_edge_event() functions
The read_edge_event() family of functions should actually be called
read_edge_events() as they universally allow to read more than one
event. We're converting wait_edge_event() too for consistency.
treewide: apply formatting changes with clang-format
Use linux kernel's .clang-format file to automatically improve the coding
style of libgpiod's C code base. We don't import the file into the
repository as it's not perfect and certain converted fragments were
rolled back because they looked better before the conversion.
bindings: python: tests: use the version parser from setuptools
We currently require the third-party packaging module to be installed in
order to run tests. Let's instead use the version parser that's already
available in setuptools.
We need to drop the reference count of the GVariants we create when
packing hogs and line names. This fixes all memory leaks in tests that
are caused by this bug.
Kent Gibson [Mon, 21 Nov 2022 10:22:51 +0000 (18:22 +0800)]
tools: add gpionotify
Add a gpionotify tool, based on gpiomon, to report line info change
events read from chip file descriptors.
Inspired by the gpio-watch tool in the linux kernel, but with gpiomon
features such as custom formatted output, filtering events of
interest and exiting after a number of events, so more useful for
scripting.
Default output is minimalist, so just time, event type and line id.
Full event details are available using the custom formatted output.
Kent Gibson [Mon, 21 Nov 2022 10:22:48 +0000 (18:22 +0800)]
tools: line name focussed rework
Rework the tool suite to support identifying lines by name and to
support operating on the GPIO lines available to the user at once, rather
than on one particular GPIO chip.
All tools, other than gpiodetect, now provide the name to (chip,offset)
mapping that was previously only performed by gpiofind. As names are not
guaranteed to be unique, a --strict option is provided for all tools to
either abort the operation or report all lines with the matching name, as
appropriate.
By default the tools operate on the first line found with a matching name.
Selection of line by (chip,offset) is still supported with a --chip
option, though it restricts the scope of the operation to an individual
chip. When the --chip option is specified, the lines are assumed to be
identified by offset where they parse as an integer, else by name.
To cater for the unusual case where a line name parses as an integer,
but is different from the offset, the --by-name option forces the lines
to be identified by name.
The updated tools are intentionally NOT backwardly compatible with the
previous tools. Using old command lines with the updated tools will
almost certainly fail, though migrating old command lines is generally as
simple as adding a '-c' before the chip.
In addition the individual tools are modified as follows:
gpiodetect:
Add the option to select individual chips.
gpioinfo:
Change the focus from chips to lines, so the scope can be
an individual line, a subset of lines, all lines on a particular chip,
or all the lines available to the user. For line scope a single line
summary is output for each line. For chip scope the existing format
displaying a summary of the chip and each of its lines is retained.
Line attributes are consolidated into a list format, and are extended
to cover all attributes supported by uAPI v2.
gpioget:
The default output format is becomes line=value, as per the
input for gpioset, and the value is reported as active or inactive,
rather than 0 or 1.
The previous format is available using the --numeric option.
Add an optional hold period between requesting a line and reading the
value to allow the line to settle once the requested configuration has
been applied (e.g. bias).
gpiomon:
Consolidate the edge options into a single option.
Add a debounce period option.
Add options to report event times as UTC or localtime.
Add format specifiers for GPIO chip path, line name, stringified event
type, and event time as a datetime.
Rearrange default output format to place fields with more predicable
widths to the left, and to separate major field groups with tabs.
Lines are identified consistent with the command line.
gpioset:
Add a hold period option that specifies the minimum period the line
value must be held for. This applies to all set options.
Support line values specified as active/inactive, on/off and
true/false, as well as 1/0.
Add a toggle option that specifies a time sequence over which the
requested lines should be toggled. If the sequence is 0 terminated then
gpioset exits when the sequence completes, else it repeats the sequence.
This allows for anything from simple blinkers to bit bashing from the
command line. e.g. gpioset -t 500ms LED=on
Add an interactive option to provide a shell-like interface to allow
manual or scripted manipulation of requested lines. A basic command set
allows lines to be get, set, or toggled, and to insert sleeps between
operations.
Remove the --mode, --sec, and --usec options.
The combination of hold period and interactive mode provide functionality
equivalent to the old --mode options. By default gpioset now holds the
line indefinitely, rather than exiting immediately. The old exit
behaviour can be emulated with a "-t 0" option.
Signed-off-by: Kent Gibson <warthog618@gmail.com>
[Bartosz: coding style tweaks, dropped stray newlines and spaces] Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
This commit is the result of a squash of all the commits created during
the development of libgpiod v2. This is done to preserve bisectability
of the git tree. It contains significant re-writes of the core C library
as well as C++ and python bindings. The tools have been adjusted to work
with the new API but have not undergone significant changes yet.
This commit contains the bulk of the work on libgpiod v2 but the
development continues with more changes planned.
Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
[Ben: fix format specifier for uint64_t] Signed-off-by: Ben Hutchings <ben.hutchings@mind.be>
[Viresh: Fix ioctl number for gpiod_line_request_reconfigure_lines()] Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
[Kent: bug fixes, improvements, better pointer contracts, type strictness] Signed-off-by: Kent Gibson <warthog618@gmail.com>
gpiosim: initialize the bank's num_lines field to 1
If we create a simulated chip and never set the num_lines property, the
num_lines field remains set to 0 and the potential lineX and hog
directories within the bank's directory will not get removed so the
removal of the bank's and device's directories will fail too leaving
a dangling chip in place.
Initialize bank->num_lines to 1 to avoid this issue.
Fixes: a2f6e8cd3540 ("libgpiosim: new library for controlling the gpio-sim module") Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
If a bank gets released before the device is disabled, the sysfs file
descriptor of that bank is leaked. close() it when releasing the bank.
While at it: improve two other details - unlink the configfs directory
after closing the file descriptor associated with it and remove an
unnecessary check when closing the sysfs descriptor when disabling the
device.
gpiosim: add an enum representing line active state
In order to avoid confusion and stress the fact that "value" represents
the logical state of a GPIO line, add a two-value enum with the names
"ACTIVE" and "INACTIVE" to the libgpiosim API.
If a bank gets dropped when the device is still enabled and before the
parent device, we leak the device path and chip name strings. This makes
sure we always free them.
Joel Stanley [Wed, 2 Feb 2022 12:01:23 +0000 (22:31 +1030)]
gpioinfo: Clean up scandir allocations
==3017== 176 (80 direct, 96 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
==3017== at 0x483F6C7: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==3017== by 0x491CE92: ??? (in /lib/libc.so.6)
==3017== by 0x10AAAC: main (gpioinfo.c:215)
The entires must be freed, and then the array itself.
Signed-off-by: Joel Stanley <joel@jms.id.au> Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
Joel Stanley [Wed, 2 Feb 2022 12:32:48 +0000 (23:02 +1030)]
core: Fix gpiod_line_bulk_reset type
bulk->lines is an array of pointers, so it doesn't matter which pointer
type we specify to sizeof(). As it's a struct gpiod_line *, it would
make sense to use that.
Signed-off-by: Joel Stanley <joel@jms.id.au> Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
libgpiosim: new library for controlling the gpio-sim module
Add a C library for controlling the gpio-sim kernel module from various
libgpiod test suites. This aims at replacing the old gpio-mockup module
and its user-space library - libgpio-mockup - in the project's tree.
I noticed that tools ptests fail on minimal yocto systems and the
culprit of that is missing the timeout command. Check for it before
launching the bats suite.
The current proposed v2.0 API for libgpiod contains so many changes
since v1.x that the items in TODO have become obsolete. For instance:
we can no longer rethink the bulk line objects because they no longer
exist. Same for C++ weak references - in the new version the objects
will no longer be copyable. Remove the libgpiod v2 items entirely.
Ahmad Fatoum [Tue, 27 Apr 2021 15:42:24 +0000 (17:42 +0200)]
tools: gpioget: add new --dir-as-is option for GPO read-back
Both legacy sysfs and new character device API support querying line
state of a GPIO configured as output. But while sysfs /value can
be read for these output GPIOs, gpioget unconditionally muxes the
line as input. To ease migration to the new user API, add a new
--dir-as-is parameter that doesn't force the line to input.
This is especially useful for GPIO controllers that maintain their
last configured output state.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
Currently libgpiod requires that the GPIO chip character device be named
'gpiochip%u' in devfs. However it's a perfectly valid use-case to have
the device file renamed by udev (or equivalent) to anything else.
Modify gpiod_is_gpiochip_device() to check the major and minor device
numbers first and then ensure that the device in question is associated
with the GPIO subsystem. No longer check the name.
Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl> Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
GPIOD_API is unneccesarily polluting the user-facing headers. There's no
advantage to having it in public files. Let's make them internal to the
library. Upcoming modifications will also make GPIOD_BIT() redundant so
we'll be able to remove all macros unrelated to the main functionality
from gpiod.h.
This removes any trace of line updating from the API (C, C++ and Python).
The line objects will soon disappear entirely so in order to make the
gradual transition to the new data model easier, remove
gpiod_line_update().
This removes another two functions from the C API as well as their
bindings that don't make much sense (since the user should know if
they have requested the line or not).
core: switch to reference counting for gpio chip objects
The preferred approach in low-level system libraries is to make all
exposed data structures opaque and use reference counting for their
memory management. This changes the chip objects to only close their
underlying character device and release all resources once the reference
count goes down to 0. We remove the gpiod_chip_close() function and
replace it with gpiod_chip_ref() and gpiod_chip_unref().
Other objects in the API will either be removed or are not opaque yet
and will be reworked later.
Together with the removal of line objects, we'll entirely drop the
line bulk concept. In order to avoid having to update tests that will
soon be unneeded when introducing further changes, let's remove line
bulk test cases already.
We're preparing to entirely remove the line objects from the API and
split their functionality between two new objects: line_info and
line_request. The lookup functions must be limited in the process.
This reworks all the find_line methods to: a) always assume that names
looked for are unique within a single chip (because while it's
technically possible for GPIO line names to be non-unique, it doesn't
make sense to look for two lines named the same) and b) return the
hardware offset within the chip instead of the line object.
While not necessary to compile, the PyObject_HEAD macros look more
consistent with the rest of the code if they too have semicolons at the
end of the lines.