Merge pull request #1725 from mhei/support-for-libgpiodv2

Add support for libgpiod v2+ API
This commit is contained in:
Stefan Rueger
2024-04-17 00:38:24 +01:00
committed by GitHub
5 changed files with 222 additions and 12 deletions

View File

@@ -126,7 +126,6 @@ if(USE_STATIC_LIBS)
set(PREFERRED_LIBFTDI1 libftdi1.a ftdi1)
set(PREFERRED_LIBREADLINE libreadline.a readline)
set(PREFERRED_LIBSERIALPORT libserialport.a serialport)
set(PREFERRED_LIBGPIOD libgpiod.a gpiod)
else()
set(PREFERRED_LIBELF elf)
set(PREFERRED_LIBUSB usb)
@@ -136,7 +135,6 @@ else()
set(PREFERRED_LIBFTDI1 ftdi1)
set(PREFERRED_LIBREADLINE readline)
set(PREFERRED_LIBSERIALPORT serialport)
set(PREFERRED_LIBGPIOD gpiod)
endif()
# -------------------------------------
@@ -237,12 +235,32 @@ if(HAVE_LIBSERIALPORT)
endif()
# -------------------------------------
# Find libgpiod, if needed
# Find libgpiod using pkg-config, if needed
if(HAVE_LINUXGPIO)
find_library(HAVE_LIBGPIOD NAMES ${PREFERRED_LIBGPIOD})
if(HAVE_LIBGPIOD)
set(LIB_LIBGPIOD ${HAVE_LIBGPIOD})
set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIBGPIOD})
# defaults/fallbacks
set(HAVE_LIBGPIOD 0)
set(HAVE_LIBGPIOD_V2 0)
find_package(PkgConfig)
if(PKG_CONFIG_FOUND)
# check whether we have version >= 2.0
pkg_check_modules(LIBGPIODV2 libgpiod>=2.0)
if(LIBGPIODV2_FOUND)
set(HAVE_LIBGPIOD 1)
set(HAVE_LIBGPIOD_V2 1)
set(CMAKE_REQUIRED_LIBRARIES ${LIBGPIODV2_LIBRARIES})
set(LIB_LIBGPIOD ${LIBGPIODV2_LINK_LIBRARIES})
else()
# check whether we have at least an older version
pkg_check_modules(LIBGPIOD libgpiod)
if(LIBGPIOD_FOUND)
set(HAVE_LIBGPIOD 1)
set(CMAKE_REQUIRED_LIBRARIES ${LIBGPIOD_LIBRARIES})
set(LIB_LIBGPIOD ${LIBGPIOD_LINK_LIBRARIES})
endif()
endif()
else()
message(WARNING "For using libgpiod, pkg-config would be required which is not available.")
endif()
endif()
@@ -339,7 +357,8 @@ if (DEBUG_CMAKE)
message(STATUS "HAVE_LIBUSB_1_0_LIBUSB_H: ${HAVE_LIBUSB_1_0_LIBUSB_H}")
message(STATUS "HAVE_HIDAPI_HIDAPI_H: ${HAVE_HIDAPI_HIDAPI_H}")
message(STATUS "LIBUSB_COMPAT_DIR: ${LIBUSB_COMPAT_DIR}")
message(STATUS "HAVE_LIBGPIOD: ${HAVE_LIBGPIOD}")
message(STATUS "LIBGPIODV2_FOUND: ${LIBGPIODV2_FOUND}")
message(STATUS "LIBGPIOD_FOUND: ${LIBGPIOD_FOUND}")
message(STATUS "----------------------")
endif()
@@ -409,7 +428,9 @@ endif()
if(HAVE_LINUXGPIO)
message(STATUS "ENABLED linuxgpio")
if (HAVE_LIBGPIOD)
if (LIBGPIODV2_FOUND)
message(STATUS "DO HAVE libgpiod (v2.x)")
elseif(LIBGPIOD_FOUND)
message(STATUS "DO HAVE libgpiod")
else()
message(STATUS "DON'T HAVE libgpiod")

View File

@@ -62,10 +62,10 @@ libavrdude_la_CPPFLAGS = $(libavrdude_a_CPPFLAGS)
avrdude_CFLAGS = @ENABLE_WARNINGS@
libavrdude_a_CFLAGS = @ENABLE_WARNINGS@
libavrdude_a_CFLAGS = @ENABLE_WARNINGS@ $(LIBGPIOD_CFLAGS)
libavrdude_la_CFLAGS = $(libavrdude_a_CFLAGS)
avrdude_LDADD = $(top_builddir)/$(noinst_LIBRARIES) @LIBUSB_1_0@ @LIBHIDAPI@ @LIBUSB@ @LIBFTDI1@ @LIBFTDI@ @LIBHID@ @LIBELF@ @LIBPTHREAD@ @LIBSERIALPORT@ -lm
avrdude_LDADD = $(top_builddir)/$(noinst_LIBRARIES) @LIBUSB_1_0@ @LIBHIDAPI@ @LIBUSB@ @LIBFTDI1@ @LIBFTDI@ @LIBHID@ @LIBELF@ @LIBPTHREAD@ @LIBSERIALPORT@ $(LIBGPIOD_LIBS) -lm
bin_PROGRAMS = avrdude

View File

@@ -30,6 +30,9 @@
/* Let linuxgpio know if libgpiod is available. */
#cmakedefine HAVE_LIBGPIOD
/* Let linuxgpio know whether v2 of libgpiod is available. */
#cmakedefine HAVE_LIBGPIOD_V2
/* Linux SPI support enabled */
#cmakedefine HAVE_LINUXSPI 1

View File

@@ -99,6 +99,13 @@ AC_PROG_LEX([noyywrap])
AM_PROG_AR
LT_INIT()
# If macro PKG_PROG_PKG_CONFIG is not available, Autoconf generates a misleading error message,
# so check for existence first, and otherwise provide helpful advice.
m4_ifndef([PKG_PROG_PKG_CONFIG], [m4_fatal(m4_normalize([
Macro PKG_PROG_PKG_CONFIG is not available.
It is usually defined in file pkg.m4 provided by package pkg-config.]))])
PKG_PROG_PKG_CONFIG([0.23])
AH_TEMPLATE([HAVE_YYLEX_DESTROY],
[Define if lex/flex has yylex_destroy])
# flex should have this
@@ -411,7 +418,7 @@ AC_ARG_ENABLE(
AC_ARG_ENABLE(
[linuxgpio],
AS_HELP_STRING([--enable-linuxgpio],
[Enable the Linux sysfs GPIO interface programmer type]),
[Enable the Linux GPIO interface programmer type]),
[case "${enableval}" in
yes) enabled_linuxgpio=yes ;;
no) enabled_linuxgpio=no ;;
@@ -517,6 +524,22 @@ fi
if test "x$enabled_linuxgpio" = xyes; then
AC_DEFINE([HAVE_LINUXGPIO], [1], [Linux sysfs GPIO support enabled])
confsubst="$confsubst -e /^@HAVE_LINUXGPIO_/d"
PKG_CHECK_MODULES([LIBGPIOD], [libgpiod >= 2.0], [
have_libgpiod=yes
have_libgpiodv2=yes
AC_DEFINE([HAVE_LIBGPIOD], [1], [Linux libgpiod available])
AC_DEFINE([HAVE_LIBGPIOD_V2], [1], [Linux libgpiod (v2.x) available])
], [
PKG_CHECK_MODULES([LIBGPIOD], [libgpiod], [
have_libgpiod=yes
have_libgpiodv2=no
AC_DEFINE([HAVE_LIBGPIOD], [1], [Linux libgpiod available])
], [
have_libgpiod=no
have_libgpiodv2=no
])
])
else
confsubst="$confsubst -e /^@HAVE_LINUXGPIO_BEGIN@/,/^@HAVE_LINUXGPIO_END@/d"
fi
@@ -724,6 +747,13 @@ fi
if test "x$enabled_linuxgpio" = xyes; then
echo "ENABLED linuxgpio"
if test "x$have_libgpiodv2" = xyes; then
echo "DO HAVE libgpiod (v2.x)"
elif test "x$have_libgpiod" = xyes; then
echo "DO HAVE libgpiod"
else
echo "DON'T HAVE libgpiod"
fi
else
echo "DISABLED linuxgpio"
fi

View File

@@ -337,6 +337,162 @@ static void linuxgpio_sysfs_close(PROGRAMMER *pgm)
#ifdef HAVE_LIBGPIOD
#ifdef HAVE_LIBGPIOD_V2
struct gpiod_line {
struct gpiod_chip *chip;
struct gpiod_line_request *line_request;
unsigned int gpio_num;
};
struct gpiod_line *gpiod_line_get(const char *port, int gpio_num) {
struct gpiod_line *rv;
char abs_port[32];
if (snprintf(abs_port, sizeof(abs_port), "/dev/%s", port) >= (int)sizeof(abs_port))
return NULL;
rv = calloc(sizeof(struct gpiod_line), 1);
if (!rv)
return NULL;
rv->gpio_num = gpio_num;
rv->chip = gpiod_chip_open(abs_port);
if (!rv->chip) {
free(rv);
return NULL;
}
return rv;
}
int gpiod_line_request_input(struct gpiod_line *gpio_line, const char *consumer) {
struct gpiod_line_settings *line_settings = NULL;
struct gpiod_line_config *line_config = NULL;
struct gpiod_request_config *req_cfg = NULL;
int retval = -1;
line_settings = gpiod_line_settings_new();
line_config = gpiod_line_config_new();
req_cfg = gpiod_request_config_new();
if (!line_settings || !line_config || !req_cfg)
goto err_out;
retval = gpiod_line_settings_set_direction(line_settings, GPIOD_LINE_DIRECTION_INPUT);
if (retval != 0)
goto err_out;
retval = gpiod_line_config_add_line_settings(line_config, &gpio_line->gpio_num, 1, line_settings);
if (retval != 0)
goto err_out;
gpiod_request_config_set_consumer(req_cfg, consumer);
gpio_line->line_request = gpiod_chip_request_lines(gpio_line->chip, req_cfg, line_config);
if (!gpio_line->line_request)
goto err_out;
retval = 0;
err_out:
gpiod_line_settings_free(line_settings);
gpiod_line_config_free(line_config);
gpiod_request_config_free(req_cfg);
return retval;
}
int gpiod_line_request_output(struct gpiod_line *gpio_line, const char *consumer, int value) {
struct gpiod_line_settings *line_settings = NULL;
struct gpiod_line_config *line_config = NULL;
struct gpiod_request_config *req_cfg = NULL;
int retval = -1;
line_settings = gpiod_line_settings_new();
line_config = gpiod_line_config_new();
req_cfg = gpiod_request_config_new();
if (!line_settings || !line_config || !req_cfg)
goto err_out;
retval = gpiod_line_settings_set_direction(line_settings, GPIOD_LINE_DIRECTION_OUTPUT);
if (retval != 0)
goto err_out;
retval = gpiod_line_settings_set_output_value(line_settings, value ? GPIOD_LINE_VALUE_ACTIVE : GPIOD_LINE_VALUE_INACTIVE);
if (retval != 0)
goto err_out;
retval = gpiod_line_config_add_line_settings(line_config, &gpio_line->gpio_num, 1, line_settings);
if (retval != 0)
goto err_out;
gpiod_request_config_set_consumer(req_cfg, consumer);
gpio_line->line_request = gpiod_chip_request_lines(gpio_line->chip, req_cfg, line_config);
if (!gpio_line->line_request)
goto err_out;
retval = 0;
err_out:
gpiod_line_settings_free(line_settings);
gpiod_line_config_free(line_config);
gpiod_request_config_free(req_cfg);
return retval;
}
int gpiod_line_set_direction_input(struct gpiod_line *gpio_line) {
struct gpiod_line_settings *line_settings = NULL;
struct gpiod_line_config *line_config = NULL;
int retval = -1;
line_settings = gpiod_line_settings_new();
line_config = gpiod_line_config_new();
if (!line_settings || !line_config)
goto err_out;
retval = gpiod_line_settings_set_direction(line_settings, GPIOD_LINE_DIRECTION_INPUT);
if (retval != 0)
goto err_out;
retval = gpiod_line_config_add_line_settings(line_config, &gpio_line->gpio_num, 1, line_settings);
if (retval != 0)
goto err_out;
retval = gpiod_line_request_reconfigure_lines(gpio_line->line_request, line_config);
err_out:
gpiod_line_settings_free(line_settings);
gpiod_line_config_free(line_config);
return retval;
}
/* this helper is not thread safe, but we are not using threads... */
char *gpiod_line_name(struct gpiod_line *gpio_line) {
static char buffer[16];
snprintf(buffer, sizeof(buffer), "%u", gpio_line->gpio_num);
return buffer;
}
void gpiod_line_release(struct gpiod_line *gpio_line) {
gpiod_line_request_release(gpio_line->line_request);
gpiod_chip_close(gpio_line->chip);
free(gpio_line);
}
static inline int gpiod_line_set_value(struct gpiod_line *gpio_line, int value) {
return gpiod_line_request_set_value(gpio_line->line_request, gpio_line->gpio_num, value);
}
static inline int gpiod_line_get_value(struct gpiod_line *gpio_line) {
return gpiod_line_request_get_value(gpio_line->line_request, gpio_line->gpio_num);
}
#endif
struct gpiod_line * linuxgpio_libgpiod_lines[N_PINS];
// Try to tell if libgpiod is going to work.