From 6a75ac7057d52fc349b88293177068649df1c4f0 Mon Sep 17 00:00:00 2001 From: Michael Heimpold Date: Mon, 22 Apr 2024 23:11:33 +0200 Subject: [PATCH] linuxgpio: add gpiod_line_set_direction_input helper for libgpiod v1.4 support (refs #1782) This ancient libgpiod version is still shipped on Ubuntu 20.04 LTS. Add support for it by adding another helper. Signed-off-by: Michael Heimpold --- CMakeLists.txt | 25 +++++++++++++++++++------ src/cmake_config.h.in | 7 +++++-- src/configure.ac | 23 +++++++++++++++++------ src/linuxgpio.c | 26 +++++++++++++++++++++++++- 4 files changed, 66 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6bfe3654..7adc7ae8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -240,6 +240,7 @@ if(HAVE_LINUXGPIO) # defaults/fallbacks set(HAVE_LIBGPIOD 0) set(HAVE_LIBGPIOD_V2 0) + set(HAVE_LIBGPIOD_V1_6 0) find_package(PkgConfig) if(PKG_CONFIG_FOUND) @@ -251,12 +252,21 @@ if(HAVE_LINUXGPIO) 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) + # check whether we have version >= 1.6 + pkg_check_modules(LIBGPIODV1_6 libgpiod>=1.6) + if(LIBGPIODV1_6_FOUND) set(HAVE_LIBGPIOD 1) - set(CMAKE_REQUIRED_LIBRARIES ${LIBGPIOD_LIBRARIES}) - set(LIB_LIBGPIOD ${LIBGPIOD_LINK_LIBRARIES}) + set(HAVE_LIBGPIOD_V1_6 1) + set(CMAKE_REQUIRED_LIBRARIES ${LIBGPIODV1_6_LIBRARIES}) + set(LIB_LIBGPIOD ${LIBGPIODV1_6_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() endif() else() @@ -358,6 +368,7 @@ if (DEBUG_CMAKE) message(STATUS "HAVE_HIDAPI_HIDAPI_H: ${HAVE_HIDAPI_HIDAPI_H}") message(STATUS "LIBUSB_COMPAT_DIR: ${LIBUSB_COMPAT_DIR}") message(STATUS "LIBGPIODV2_FOUND: ${LIBGPIODV2_FOUND}") + message(STATUS "LIBGPIODV1_6_FOUND: ${LIBGPIODV1_6_FOUND}") message(STATUS "LIBGPIOD_FOUND: ${LIBGPIOD_FOUND}") message(STATUS "----------------------") endif() @@ -429,7 +440,9 @@ endif() if(HAVE_LINUXGPIO) message(STATUS "ENABLED linuxgpio") if (LIBGPIODV2_FOUND) - message(STATUS "DO HAVE libgpiod (v2.x)") + message(STATUS "DO HAVE libgpiod (>=2.0)") + elseif(LIBGPIODV1_6_FOUND) + message(STATUS "DO HAVE libgpiod (>=1.6)") elseif(LIBGPIOD_FOUND) message(STATUS "DO HAVE libgpiod") else() diff --git a/src/cmake_config.h.in b/src/cmake_config.h.in index d68e122f..f11ca00c 100644 --- a/src/cmake_config.h.in +++ b/src/cmake_config.h.in @@ -30,8 +30,11 @@ /* Let linuxgpio know if libgpiod is available. */ #cmakedefine HAVE_LIBGPIOD -/* Let linuxgpio know whether v2 of libgpiod is available. */ -#cmakedefine HAVE_LIBGPIOD_V2 +/* Let linuxgpio know whether libgpiod is available in version >= v1.6 but < v2.0. */ +#cmakedefine01 HAVE_LIBGPIOD_V1_6 + +/* Let linuxgpio know whether v2.0 or higher of libgpiod is available. */ +#cmakedefine01 HAVE_LIBGPIOD_V2 /* Linux SPI support enabled */ #cmakedefine HAVE_LINUXSPI 1 diff --git a/src/configure.ac b/src/configure.ac index 8b2d4ea3..be155b9a 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -529,17 +529,26 @@ if test "x$enabled_linuxgpio" = xyes; then 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]) + AC_DEFINE([HAVE_LIBGPIOD_V1_6], [0], [Linux libgpiod >= v1.6 but < 2.0 available]) + AC_DEFINE([HAVE_LIBGPIOD_V2], [1], [Linux libgpiod >= 2.0 available]) ], [ - PKG_CHECK_MODULES([LIBGPIOD], [libgpiod], [ + PKG_CHECK_MODULES([LIBGPIOD], [libgpiod >= 1.6], [ have_libgpiod=yes - have_libgpiodv2=no + have_libgpiodv1_6=yes AC_DEFINE([HAVE_LIBGPIOD], [1], [Linux libgpiod available]) + AC_DEFINE([HAVE_LIBGPIOD_V1_6], [1], [Linux libgpiod >= v1.6 but < 2.0 available]) + AC_DEFINE([HAVE_LIBGPIOD_V2], [0], [Linux libgpiod >= 2.0 available]) ], [ - have_libgpiod=no - have_libgpiodv2=no + PKG_CHECK_MODULES([LIBGPIOD], [libgpiod], [ + have_libgpiod=yes + AC_DEFINE([HAVE_LIBGPIOD_V1_6], [0], [Linux libgpiod >= v1.6 but < 2.0 available]) + AC_DEFINE([HAVE_LIBGPIOD_V2], [0], [Linux libgpiod >= 2.0 available]) + ], [ + have_libgpiod=no + ]) ]) ]) + else confsubst="$confsubst -e /^@HAVE_LINUXGPIO_BEGIN@/,/^@HAVE_LINUXGPIO_END@/d" fi @@ -748,7 +757,9 @@ fi if test "x$enabled_linuxgpio" = xyes; then echo "ENABLED linuxgpio" if test "x$have_libgpiodv2" = xyes; then - echo "DO HAVE libgpiod (v2.x)" + echo "DO HAVE libgpiod (>=2.0)" + elif test "x$have_libgpiodv1_6" = xyes; then + echo "DO HAVE libgpiod (>=1.6)" elif test "x$have_libgpiod" = xyes; then echo "DO HAVE libgpiod" else diff --git a/src/linuxgpio.c b/src/linuxgpio.c index 7b54f6fe..e5fcf67f 100644 --- a/src/linuxgpio.c +++ b/src/linuxgpio.c @@ -344,7 +344,23 @@ void linuxgpio_teardown(PROGRAMMER *pgm) { #ifdef HAVE_LIBGPIOD -#ifdef HAVE_LIBGPIOD_V2 +#if !HAVE_LIBGPIOD_V1_6 && !HAVE_LIBGPIOD_V2 + +int gpiod_line_set_direction_input(struct gpiod_line **gpio_line) { + struct gpiod_chip *chip = gpiod_line_get_chip(*gpio_line); + unsigned int gpio_num = gpiod_line_offset(*gpio_line); + + // release to pin first... + gpiod_line_release(*gpio_line); + + // so that we can re-acquire it as input + *gpio_line = gpiod_chip_get_line(chip, gpio_num); + return gpiod_line_request_input(*gpio_line, "avrdude"); +} + +#endif + +#if HAVE_LIBGPIOD_V2 struct gpiod_line { struct gpiod_chip *chip; @@ -565,7 +581,11 @@ static void linuxgpio_libgpiod_close(PROGRAMMER *pgm) { // This should avoid possible conflicts when AVR firmware starts. for (i = 0; i < N_PINS; ++i) { if (linuxgpio_libgpiod_lines[i] != NULL && i != PIN_AVR_RESET) { +#if HAVE_LIBGPIOD_V1_6 || HAVE_LIBGPIOD_V2 int r = gpiod_line_set_direction_input(linuxgpio_libgpiod_lines[i]); +#else + int r = gpiod_line_set_direction_input(&linuxgpio_libgpiod_lines[i]); +#endif if (r != 0) { msg_error("failed to set pin %u to input: %s\n", linuxgpio_libgpiod_lines[i]->gpio_num, strerror(errno)); @@ -577,7 +597,11 @@ static void linuxgpio_libgpiod_close(PROGRAMMER *pgm) { // Configure RESET as input. if (linuxgpio_libgpiod_lines[PIN_AVR_RESET] != NULL) { +#if HAVE_LIBGPIOD_V1_6 || HAVE_LIBGPIOD_V2 int r = gpiod_line_set_direction_input(linuxgpio_libgpiod_lines[PIN_AVR_RESET]); +#else + int r = gpiod_line_set_direction_input(&linuxgpio_libgpiod_lines[PIN_AVR_RESET]); +#endif if (r != 0) { msg_error("failed to set pin %u to input: %s\n", linuxgpio_libgpiod_lines[PIN_AVR_RESET]->gpio_num, strerror(errno));