diff --git a/libs/libgpiod/Makefile b/libs/libgpiod/Makefile index ef15288b1a..9c8eb9f5f4 100644 --- a/libs/libgpiod/Makefile +++ b/libs/libgpiod/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libgpiod -PKG_VERSION:=1.6.4 +PKG_VERSION:=2.1.1 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@KERNEL/software/libs/libgpiod/ -PKG_HASH:=7b146e12f28fbca3df7557f176eb778c5ccf952ca464698dba8a61b2e1e3f9b5 +PKG_HASH:=b21913f469d3135680d5516f00fdf9f81d5e564e19ffb690927ea7f1d7e312cb PKG_MAINTAINER:=Michael Heimpold PKG_LICENSE:=LGPL-2.1-or-later @@ -26,17 +26,24 @@ PYTHON3_PKG_BUILD:=0 include $(INCLUDE_DIR)/package.mk include ../../lang/python/python3-package.mk +ifneq ($(CONFIG_PACKAGE_libgpiodcxx),) +CONFIGURE_ARGS += --enable-bindings-cxx +else +CONFIGURE_ARGS += --disable-bindings-cxx +endif + ifneq ($(CONFIG_PACKAGE_gpiod-tools),) CONFIGURE_ARGS += --enable-tools endif -ifneq ($(CONFIG_PACKAGE_python3-gpiod),) -CONFIGURE_ARGS += --enable-bindings-python -CONFIGURE_VARS += \ - PYTHON="$(STAGING_DIR_HOSTPKG)/bin/$(PYTHON3)" \ - PYTHON_CPPFLAGS="$(shell $(STAGING_DIR)/host/bin/$(PYTHON3)-config --includes)" \ - PYTHON_LIBS="$(shell $(STAGING_DIR)/host/bin/$(PYTHON3)-config --libs)" -endif +PYTHON3_PKG_WHEEL_NAME:=gpiod +PYTHON3_PKG_WHEEL_VERSION:=2.0.1 + +PYTHON3_PKG_SETUP_DIR:=bindings/python +PYTHON3_PKG_SETUP_VARS += LINK_SYSTEM_LIBGPIOD=1 + +TARGET_CPPFLAGS += -I$(PKG_BUILD_DIR)/include +TARGET_LDFLAGS += -L$(PKG_BUILD_DIR)/lib/.libs define Package/libgpiod SECTION:=libs @@ -44,8 +51,7 @@ define Package/libgpiod URL:=https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git TITLE:=Library for interacting with Linux's GPIO character device KCONFIG:= \ - CONFIG_GPIO_CDEV=y \ - CONFIG_GPIO_CDEV_V1=y + CONFIG_GPIO_CDEV=y DEPENDS:=@GPIO_SUPPORT endef @@ -66,6 +72,18 @@ define Package/gpiod-tools/description (gpiod stands for GPIO device). endef +define Package/libgpiodcxx + SECTION:=libs + CATEGORY:=Libraries + URL:=https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git + TITLE:=C++ binding for libgpiod + DEPENDS:=+libstdcpp +libgpiod +endef + +define Package/libgpiodcxx/description + This package contains the C++ binding for libgpiod. +endef + define Package/python3-gpiod SECTION:=lang CATEGORY:=Languages @@ -79,6 +97,27 @@ define Package/python3-gpiod/description This package contains the Python bindings for libgpiod. endef +define Build/Configure + $(call Build/Configure/Default) + ifneq ($(CONFIG_PACKAGE_python3-gpiod),) + $(call Py3Build/Configure) + endif +endef + +define Build/Compile + $(call Build/Compile/Default) + ifneq ($(CONFIG_PACKAGE_python3-gpiod),) + $(call Py3Build/Compile) + endif +endef + +define Build/Install + $(call Build/Install/Default) + ifneq ($(CONFIG_PACKAGE_python3-gpiod),) + $(call Py3Build/Install/Default) + endif +endef + define Build/InstallDev $(INSTALL_DIR) $(1)/usr/include $(CP) $(PKG_INSTALL_DIR)/usr/include/gpiod.h $(1)/usr/include/ @@ -88,6 +127,20 @@ define Build/InstallDev $(INSTALL_DIR) $(1)/usr/lib/pkgconfig $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libgpiod.pc $(1)/usr/lib/pkgconfig/ + + ifneq ($(CONFIG_PACKAGE_libgpiodcxx),) + $(CP) $(PKG_INSTALL_DIR)/usr/include/gpiodcxx $(1)/usr/include/ + $(CP) $(PKG_INSTALL_DIR)/usr/include/gpiod.hpp $(1)/usr/include/ + + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libgpiodcxx.{so*,a} $(1)/usr/lib/ + + $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libgpiodcxx.pc $(1)/usr/lib/pkgconfig/ + endif + + ifneq ($(CONFIG_PACKAGE_python3-gpiod),) + $(INSTALL_DIR) $(1)$(PYTHON3_PKG_DIR) + $(CP) $(PKG_INSTALL_DIR)$(PYTHON3_PKG_DIR)/* $(1)$(PYTHON3_PKG_DIR) + endif endef define Package/libgpiod/install @@ -95,16 +148,23 @@ define Package/libgpiod/install $(CP) $(PKG_INSTALL_DIR)/usr/lib/libgpiod.so.* $(1)/usr/lib/ endef +define Package/libgpiodcxx/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libgpiodcxx.so.* $(1)/usr/lib/ +endef + define Package/gpiod-tools/install $(INSTALL_DIR) $(1)/usr/bin $(CP) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin/ endef -define Package/python3-gpiod/install - $(INSTALL_DIR) $(1)/$(PYTHON3_PKG_DIR) - $(CP) $(PKG_INSTALL_DIR)/$(PYTHON3_PKG_DIR)/gpiod.so $(1)/$(PYTHON3_PKG_DIR) +define Py3Package/python3-gpiod/install + # this empty define prevent installing tools from /usr/bin endef $(eval $(call BuildPackage,libgpiod)) +$(eval $(call BuildPackage,libgpiodcxx)) $(eval $(call BuildPackage,gpiod-tools)) +$(eval $(call Py3Package,python3-gpiod)) $(eval $(call BuildPackage,python3-gpiod)) +$(eval $(call BuildPackage,python3-gpiod-src)) diff --git a/utils/avrdude/Makefile b/utils/avrdude/Makefile index 84d8b78bbb..b45909b2a2 100644 --- a/utils/avrdude/Makefile +++ b/utils/avrdude/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=avrdude PKG_VERSION:=7.3 -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/avrdudes/avrdude diff --git a/utils/avrdude/patches/0001-Add-support-for-libgpiod-v2-API.patch b/utils/avrdude/patches/0001-Add-support-for-libgpiod-v2-API.patch new file mode 100644 index 0000000000..cc050e7122 --- /dev/null +++ b/utils/avrdude/patches/0001-Add-support-for-libgpiod-v2-API.patch @@ -0,0 +1,349 @@ +From 315df4ba7670a1e5190373155196a40d5a3fd54b Mon Sep 17 00:00:00 2001 +From: Michael Heimpold +Date: Wed, 27 Mar 2024 22:33:21 +0100 +Subject: [PATCH] Add support for libgpiod v2+ API + +libgpiod in version 2 or above introduced an API change which results +in compile error with the current code. + +This commit adds some glue magic for the newer versions and +tries to detect the used libgpiod version based on the information +available in the pkg-config files. + +At the moment, this eliminates the possibility to statically link +against this library. + +Signed-off-by: Michael Heimpold +(cherry picked from commit ea701bc2f59c465f48dc290e8e6cf6d14416205f) +Upstream-Status: Accepted - will be part of next release +--- + CMakeLists.txt | 39 ++++++++--- + src/Makefile.am | 4 +- + src/cmake_config.h.in | 3 + + src/configure.ac | 31 +++++++++ + src/linuxgpio.c | 156 ++++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 222 insertions(+), 11 deletions(-) + +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -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") +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -62,10 +62,10 @@ libavrdude_la_CPPFLAGS = $(libavrdude_a_ + + 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 + +--- a/src/cmake_config.h.in ++++ b/src/cmake_config.h.in +@@ -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 + +--- a/src/configure.ac ++++ b/src/configure.ac +@@ -65,6 +65,14 @@ AN_MAKEVAR([AR], [AC_PROG_AR]) + AN_PROGRAM([ar], [AC_PROG_AR]) + AC_DEFUN([AC_PROG_AR], [AC_CHECK_TARGET_TOOL(AR, ar, :)]) + AC_PROG_AR ++ ++# 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 +@@ -465,6 +473,22 @@ fi + if test "$enabled_linuxgpio" = "yes"; 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 +@@ -678,6 +702,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 +--- a/src/linuxgpio.c ++++ b/src/linuxgpio.c +@@ -337,6 +337,162 @@ static void linuxgpio_sysfs_close(PROGRA + + #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. diff --git a/utils/openocd/Makefile b/utils/openocd/Makefile index a2e7724078..3a44e56ca0 100644 --- a/utils/openocd/Makefile +++ b/utils/openocd/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=openocd PKG_SOURCE_VERSION:=v0.12.0 -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://git.code.sf.net/p/openocd/code diff --git a/utils/openocd/patches/0001-jtag-linuxgpiod-adapt-for-libgpiod-v2-API.patch b/utils/openocd/patches/0001-jtag-linuxgpiod-adapt-for-libgpiod-v2-API.patch new file mode 100644 index 0000000000..4890531215 --- /dev/null +++ b/utils/openocd/patches/0001-jtag-linuxgpiod-adapt-for-libgpiod-v2-API.patch @@ -0,0 +1,688 @@ +From 1de35c0b76ea138895370f65849831c3c7d397ff Mon Sep 17 00:00:00 2001 +From: Antonio Borneo +Date: Sun, 24 Mar 2024 15:53:33 +0100 +Subject: [PATCH] jtag: linuxgpiod: adapt for libgpiod v2 API + +Signed-off-by: Antonio Borneo +Signed-off-by: Michael Heimpold +--- + configure.ac | 15 +- + src/jtag/drivers/linuxgpiod.c | 487 ++++++++++++++++++++++++++++------ + 2 files changed, 419 insertions(+), 83 deletions(-) + +--- a/configure.ac ++++ b/configure.ac +@@ -659,7 +659,20 @@ PKG_CHECK_MODULES([LIBFTDI], [libftdi1], + PKG_CHECK_MODULES([LIBFTDI], [libftdi], [use_libftdi=yes], [use_libftdi=no]) + ]) + +-PKG_CHECK_MODULES([LIBGPIOD], [libgpiod], [use_libgpiod=yes], [use_libgpiod=no]) ++PKG_CHECK_MODULES([LIBGPIOD], [libgpiod >= 2.0] , [ ++ use_libgpiod=yes ++ AC_DEFINE([HAVE_LIBGPIOD_V1], [0], [define if libgpiod is version v1.x]) ++], [ ++ PKG_CHECK_MODULES([LIBGPIOD], [libgpiod], [ ++ use_libgpiod=yes ++ AC_DEFINE([HAVE_LIBGPIOD_V1], [1], [define if libgpiod is version v1.x]) ++ ++ PKG_CHECK_EXISTS([libgpiod >= 1.5], ++ [AC_DEFINE([HAVE_LIBGPIOD1_FLAGS_BIAS], [1], [define if libgpiod v1 has line request flags bias])]) ++ ], [ ++ use_libgpiod=no ++ ]) ++]) + + PKG_CHECK_MODULES([LIBJAYLINK], [libjaylink >= 0.2], + [use_libjaylink=yes], [use_libjaylink=no]) +--- a/src/jtag/drivers/linuxgpiod.c ++++ b/src/jtag/drivers/linuxgpiod.c +@@ -19,8 +19,267 @@ + #include + #include "bitbang.h" + ++/* ++ * In case of libgpiod v1, use as much as possible API from v2 plus ++ * the dummy wrappers below. ++ */ ++#if HAVE_LIBGPIOD_V1 ++ ++#define GPIOD_LINE_DIRECTION_INPUT GPIOD_LINE_REQUEST_DIRECTION_INPUT ++#define GPIOD_LINE_DIRECTION_OUTPUT GPIOD_LINE_REQUEST_DIRECTION_OUTPUT ++ ++#define GPIOD_LINE_VALUE_INACTIVE 0 ++#define GPIOD_LINE_VALUE_ACTIVE 1 ++ ++#define GPIOD_LINE_DRIVE_PUSH_PULL 0 ++#define GPIOD_LINE_DRIVE_OPEN_DRAIN GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN ++#define GPIOD_LINE_DRIVE_OPEN_SOURCE GPIOD_LINE_REQUEST_FLAG_OPEN_SOURCE ++ ++#define GPIOD_LINE_BIAS_DISABLED GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE ++#define GPIOD_LINE_BIAS_PULL_UP GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP ++#define GPIOD_LINE_BIAS_PULL_DOWN GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN ++ ++struct gpiod_line_settings { ++ int direction; ++ int value; ++ int drive; ++ int bias; ++ int active_low; ++}; ++ ++static struct gpiod_line_settings *gpiod_line_settings_new(void) ++{ ++ struct gpiod_line_settings *rv; ++ ++ rv = calloc(sizeof(struct gpiod_line_settings), 1); ++ if (!rv) ++ return NULL; ++ ++ return rv; ++} ++ ++static void gpiod_line_settings_free(struct gpiod_line_settings *settings) ++{ ++ free(settings); ++} ++ ++static int gpiod_line_settings_set_direction(struct gpiod_line_settings *settings, ++ int direction) ++{ ++ settings->direction = direction; ++ ++ return 0; ++} ++ ++static int gpiod_line_settings_set_output_value(struct gpiod_line_settings *settings, ++ int value) ++{ ++ settings->value = value; ++ ++ return 0; ++} ++ ++static int gpiod_line_settings_set_drive(struct gpiod_line_settings *settings, int drive) ++{ ++ settings->drive = drive; ++ ++ return 0; ++} ++ ++static void gpiod_line_settings_set_active_low(struct gpiod_line_settings *settings, ++ bool active_low) ++{ ++ if (active_low) ++ settings->active_low = GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW; ++} ++ ++#ifdef HAVE_LIBGPIOD1_FLAGS_BIAS ++ ++static int gpiod_line_settings_set_bias(struct gpiod_line_settings *settings, int bias) ++{ ++ settings->bias = bias; ++ ++ return 0; ++} ++ ++#else /* HAVE_LIBGPIOD1_FLAGS_BIAS */ ++ ++static int gpiod_line_settings_set_bias(struct gpiod_line_settings *settings, int bias) ++{ ++ if (bias == GPIOD_LINE_BIAS_DISABLED) ++ return 0; ++ ++ LOG_WARNING("linuxgpiod: ignoring request for pull-%s: not supported by libgpiod v%s", ++ (bias == GPIOD_LINE_BIAS_PULL_UP) ? "up" : "down", ++ gpiod_version_string()); ++ ++ return 0; ++} ++ ++#endif /* HAVE_LIBGPIOD1_FLAGS_BIAS */ ++ ++struct gpiod_line_config { ++ unsigned int gpio_num; ++ struct gpiod_line_settings *line_settings; ++}; ++ ++static struct gpiod_line_config *gpiod_line_config_new(void) ++{ ++ struct gpiod_line_config *rv; ++ ++ rv = calloc(sizeof(struct gpiod_line_config), 1); ++ if (!rv) ++ return NULL; ++ ++ return rv; ++} ++ ++static void gpiod_line_config_free(struct gpiod_line_config *config) ++{ ++ free(config); ++} ++ ++static int gpiod_line_config_add_line_settings(struct gpiod_line_config *config, ++ const unsigned int *offsets, size_t num_offsets, struct gpiod_line_settings *settings) ++{ ++ assert(num_offsets == 1); ++ ++ config->gpio_num = *offsets; ++ config->line_settings = settings; ++ ++ return 0; ++} ++ ++struct gpiod_request_config { ++ const char *consumer; ++}; ++ ++static struct gpiod_request_config *gpiod_request_config_new(void) ++{ ++ struct gpiod_request_config *rv; ++ ++ rv = calloc(sizeof(struct gpiod_request_config), 1); ++ if (!rv) ++ return NULL; ++ ++ return rv; ++} ++ ++static void gpiod_request_config_free(struct gpiod_request_config *config) ++{ ++ free(config); ++} ++ ++static void gpiod_request_config_set_consumer(struct gpiod_request_config *config, ++ const char *consumer) ++{ ++ config->consumer = consumer; ++} ++ ++struct gpiod_line_request { ++ struct gpiod_line *gpio_line; ++ struct gpiod_chip *chip; ++ struct gpiod_request_config *req_cfg; ++ struct gpiod_line_config *line_cfg; ++}; ++ ++static struct gpiod_line_request *gpiod_chip_request_lines(struct gpiod_chip *chip, ++ struct gpiod_request_config *req_cfg, struct gpiod_line_config *line_cfg) ++{ ++ struct gpiod_line_request *line_req; ++ int rv, flags = 0; ++ ++ assert(req_cfg); ++ ++ line_req = calloc(sizeof(struct gpiod_line_request), 1); ++ if (!line_req) ++ return NULL; ++ ++ line_req->gpio_line = gpiod_chip_get_line(chip, line_cfg->gpio_num); ++ if (!line_req->gpio_line) { ++ free(line_req); ++ return NULL; ++ } ++ ++ /* remember stuff in case we need to reconfigure later */ ++ line_req->chip = chip; ++ line_req->req_cfg = req_cfg; ++ line_req->line_cfg = line_cfg; ++ ++ flags |= line_cfg->line_settings->drive; ++ flags |= line_cfg->line_settings->bias; ++ flags |= line_cfg->line_settings->active_low; ++ ++ struct gpiod_line_request_config config = { ++ .consumer = line_req->req_cfg->consumer, ++ .request_type = line_cfg->line_settings->direction, ++ .flags = flags, ++ }; ++ ++ rv = gpiod_line_request(line_req->gpio_line, &config, line_cfg->line_settings->value); ++ if (rv < 0) { ++ gpiod_line_release(line_req->gpio_line); ++ free(line_req); ++ return NULL; ++ } ++ ++ return line_req; ++} ++ ++static int gpiod_line_request_get_value(struct gpiod_line_request *request, ++ __attribute__((unused)) unsigned int offset) ++{ ++ return gpiod_line_get_value(request->gpio_line); ++} ++ ++static int gpiod_line_request_set_value(struct gpiod_line_request *request, ++ __attribute__((unused)) unsigned int offset, int value) ++{ ++ return gpiod_line_set_value(request->gpio_line, value); ++} ++ ++static void gpiod_line_request_release(struct gpiod_line_request *request) ++{ ++ gpiod_line_release(request->gpio_line); ++ free(request); ++} ++ ++static int gpiod_line_request_reconfigure_lines(struct gpiod_line_request *request, ++ struct gpiod_line_config *line_cfg) ++{ ++ int rv, flags = 0; ++ ++ /* in libgpiod v1 we have to release the line and re-aquire it */ ++ gpiod_line_release(request->gpio_line); ++ request->gpio_line = gpiod_chip_get_line(request->chip, request->line_cfg->gpio_num); ++ if (!request->gpio_line) ++ return -1; ++ ++ flags |= line_cfg->line_settings->drive; ++ flags |= line_cfg->line_settings->bias; ++ flags |= line_cfg->line_settings->active_low; ++ ++ struct gpiod_line_request_config config = { ++ .consumer = request->req_cfg->consumer, ++ .request_type = line_cfg->line_settings->direction, ++ .flags = flags, ++ }; ++ ++ rv = gpiod_line_request(request->gpio_line, &config, line_cfg->line_settings->value); ++ if (rv < 0) ++ return -1; ++ ++ /* remember updated line_cfg */ ++ request->line_cfg = line_cfg; ++ return 0; ++} ++ ++#endif /* HAVE_LIBGPIOD_V1 */ ++ + static struct gpiod_chip *gpiod_chip[ADAPTER_GPIO_IDX_NUM] = {}; +-static struct gpiod_line *gpiod_line[ADAPTER_GPIO_IDX_NUM] = {}; ++static struct gpiod_line_settings *gpiod_line_settings[ADAPTER_GPIO_IDX_NUM] = {}; ++static struct gpiod_line_config *gpiod_line_config[ADAPTER_GPIO_IDX_NUM] = {}; ++static struct gpiod_line_request *gpiod_line_req[ADAPTER_GPIO_IDX_NUM] = {}; + + static int last_swclk; + static int last_swdio; +@@ -29,6 +288,20 @@ static bool swdio_input; + + static const struct adapter_gpio_config *adapter_gpio_config; + ++/* Helper to get/set a single line */ ++static int linuxgpiod_line_get_value(enum adapter_gpio_config_index idx) ++{ ++ return gpiod_line_request_get_value(gpiod_line_req[idx], ++ adapter_gpio_config[idx].gpio_num); ++} ++ ++static int linuxgpiod_line_set_value(enum adapter_gpio_config_index idx, int value) ++{ ++ return gpiod_line_request_set_value(gpiod_line_req[idx], ++ adapter_gpio_config[idx].gpio_num, ++ value); ++} ++ + /* + * Helper function to determine if gpio config is valid + * +@@ -48,7 +321,7 @@ static bb_value_t linuxgpiod_read(void) + { + int retval; + +- retval = gpiod_line_get_value(gpiod_line[ADAPTER_GPIO_IDX_TDO]); ++ retval = linuxgpiod_line_get_value(ADAPTER_GPIO_IDX_TDO); + if (retval < 0) { + LOG_WARNING("reading tdo failed"); + return 0; +@@ -81,20 +354,20 @@ static int linuxgpiod_write(int tck, int + } + + if (tdi != last_tdi) { +- retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_TDI], tdi); ++ retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_TDI, tdi); + if (retval < 0) + LOG_WARNING("writing tdi failed"); + } + + if (tms != last_tms) { +- retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_TMS], tms); ++ retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_TMS, tms); + if (retval < 0) + LOG_WARNING("writing tms failed"); + } + + /* write clk last */ + if (tck != last_tck) { +- retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_TCK], tck); ++ retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_TCK, tck); + if (retval < 0) + LOG_WARNING("writing tck failed"); + } +@@ -110,7 +383,7 @@ static int linuxgpiod_swdio_read(void) + { + int retval; + +- retval = gpiod_line_get_value(gpiod_line[ADAPTER_GPIO_IDX_SWDIO]); ++ retval = linuxgpiod_line_get_value(ADAPTER_GPIO_IDX_SWDIO); + if (retval < 0) { + LOG_WARNING("Fail read swdio"); + return 0; +@@ -123,30 +396,54 @@ static void linuxgpiod_swdio_drive(bool + { + int retval; + +- /* +- * FIXME: change direction requires release and re-require the line +- * https://stackoverflow.com/questions/58735140/ +- * this would change in future libgpiod +- */ +- gpiod_line_release(gpiod_line[ADAPTER_GPIO_IDX_SWDIO]); +- + if (is_output) { +- if (gpiod_line[ADAPTER_GPIO_IDX_SWDIO_DIR]) { +- retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SWDIO_DIR], 1); ++ if (gpiod_line_req[ADAPTER_GPIO_IDX_SWDIO_DIR]) { ++ retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_SWDIO_DIR, 1); + if (retval < 0) +- LOG_WARNING("Fail set swdio_dir"); ++ LOG_WARNING("Failed to set swdio_dir=1"); + } +- retval = gpiod_line_request_output(gpiod_line[ADAPTER_GPIO_IDX_SWDIO], "OpenOCD", 1); ++ ++ retval = gpiod_line_settings_set_direction(gpiod_line_settings[ADAPTER_GPIO_IDX_SWDIO], ++ GPIOD_LINE_DIRECTION_OUTPUT); + if (retval < 0) +- LOG_WARNING("Fail request_output line swdio"); ++ LOG_WARNING("Failed to set new direction of swdio"); ++ ++ retval = gpiod_line_settings_set_output_value(gpiod_line_settings[ADAPTER_GPIO_IDX_SWDIO], ++ GPIOD_LINE_VALUE_ACTIVE); ++ if (retval < 0) ++ LOG_WARNING("Failed to set output value of swdio"); ++ ++ retval = gpiod_line_config_add_line_settings(gpiod_line_config[ADAPTER_GPIO_IDX_SWDIO], ++ (unsigned int *)&adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num, 1, ++ gpiod_line_settings[ADAPTER_GPIO_IDX_SWDIO]); ++ if (retval < 0) ++ LOG_WARNING("Failed to apply output configuration to swdio"); ++ ++ retval = gpiod_line_request_reconfigure_lines(gpiod_line_req[ADAPTER_GPIO_IDX_SWDIO], ++ gpiod_line_config[ADAPTER_GPIO_IDX_SWDIO]); ++ if (retval < 0) ++ LOG_WARNING("Failed to switch swdio to output"); + } else { +- retval = gpiod_line_request_input(gpiod_line[ADAPTER_GPIO_IDX_SWDIO], "OpenOCD"); ++ retval = gpiod_line_settings_set_direction(gpiod_line_settings[ADAPTER_GPIO_IDX_SWDIO], ++ GPIOD_LINE_DIRECTION_INPUT); ++ if (retval < 0) ++ LOG_WARNING("Failed to switch swdio to output"); ++ ++ retval = gpiod_line_config_add_line_settings(gpiod_line_config[ADAPTER_GPIO_IDX_SWDIO], ++ (unsigned int *)&adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num, 1, ++ gpiod_line_settings[ADAPTER_GPIO_IDX_SWDIO]); + if (retval < 0) +- LOG_WARNING("Fail request_input line swdio"); +- if (gpiod_line[ADAPTER_GPIO_IDX_SWDIO_DIR]) { +- retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SWDIO_DIR], 0); ++ LOG_WARNING("Failed to apply input configuration to swdio"); ++ ++ retval = gpiod_line_request_reconfigure_lines(gpiod_line_req[ADAPTER_GPIO_IDX_SWDIO], ++ gpiod_line_config[ADAPTER_GPIO_IDX_SWDIO]); ++ if (retval < 0) ++ LOG_WARNING("Failed to switch swdio to input"); ++ ++ if (gpiod_line_req[ADAPTER_GPIO_IDX_SWDIO_DIR]) { ++ retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_SWDIO_DIR, 0); + if (retval < 0) +- LOG_WARNING("Fail set swdio_dir"); ++ LOG_WARNING("Failed to set swdio_dir=0"); + } + } + +@@ -159,16 +456,16 @@ static int linuxgpiod_swd_write(int swcl + int retval; + + if (!swdio_input) { +- if (!last_stored || (swdio != last_swdio)) { +- retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SWDIO], swdio); ++ if (!last_stored || swdio != last_swdio) { ++ retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_SWDIO, swdio); + if (retval < 0) + LOG_WARNING("Fail set swdio"); + } + } + + /* write swclk last */ +- if (!last_stored || (swclk != last_swclk)) { +- retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SWCLK], swclk); ++ if (!last_stored || swclk != last_swclk) { ++ retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_SWCLK, swclk); + if (retval < 0) + LOG_WARNING("Fail set swclk"); + } +@@ -187,7 +484,7 @@ static int linuxgpiod_blink(int on) + if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_LED)) + return ERROR_OK; + +- retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_LED], on); ++ retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_LED, on); + if (retval < 0) + LOG_WARNING("Fail set led"); + return retval; +@@ -214,17 +511,17 @@ static int linuxgpiod_reset(int trst, in + LOG_DEBUG("linuxgpiod_reset"); + + /* +- * active low behaviour handled by "adaptor gpio" command and ++ * active low behavior handled by "adaptor gpio" command and + * GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW flag when requesting the line. + */ +- if (gpiod_line[ADAPTER_GPIO_IDX_SRST]) { +- retval1 = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SRST], srst); ++ if (gpiod_line_req[ADAPTER_GPIO_IDX_SRST]) { ++ retval1 = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_SRST, srst); + if (retval1 < 0) + LOG_WARNING("set srst value failed"); + } + +- if (gpiod_line[ADAPTER_GPIO_IDX_TRST]) { +- retval2 = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_TRST], trst); ++ if (gpiod_line_req[ADAPTER_GPIO_IDX_TRST]) { ++ retval2 = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_TRST, trst); + if (retval2 < 0) + LOG_WARNING("set trst value failed"); + } +@@ -256,9 +553,17 @@ static bool linuxgpiod_swd_mode_possible + + static inline void helper_release(enum adapter_gpio_config_index idx) + { +- if (gpiod_line[idx]) { +- gpiod_line_release(gpiod_line[idx]); +- gpiod_line[idx] = NULL; ++ if (gpiod_line_req[idx]) { ++ gpiod_line_request_release(gpiod_line_req[idx]); ++ gpiod_line_req[idx] = NULL; ++ } ++ if (gpiod_line_config[idx]) { ++ gpiod_line_config_free(gpiod_line_config[idx]); ++ gpiod_line_config[idx] = NULL; ++ } ++ if (gpiod_line_settings[idx]) { ++ gpiod_line_settings_free(gpiod_line_settings[idx]); ++ gpiod_line_settings[idx] = NULL; + } + if (gpiod_chip[idx]) { + gpiod_chip_close(gpiod_chip[idx]); +@@ -277,84 +582,102 @@ static int linuxgpiod_quit(void) + + static int helper_get_line(enum adapter_gpio_config_index idx) + { ++ struct gpiod_request_config *req_cfg = NULL; ++ char chip_path[24]; ++ int rv = 0; ++ + if (!is_gpio_config_valid(idx)) + return ERROR_OK; + +- int dir = GPIOD_LINE_REQUEST_DIRECTION_INPUT, flags = 0, val = 0, retval; +- +- gpiod_chip[idx] = gpiod_chip_open_by_number(adapter_gpio_config[idx].chip_num); ++ snprintf(chip_path, sizeof(chip_path), "/dev/gpiochip%u", adapter_gpio_config[idx].chip_num); ++ gpiod_chip[idx] = gpiod_chip_open(chip_path); + if (!gpiod_chip[idx]) { + LOG_ERROR("Cannot open LinuxGPIOD chip %d for %s", adapter_gpio_config[idx].chip_num, + adapter_gpio_get_name(idx)); + return ERROR_JTAG_INIT_FAILED; + } + +- gpiod_line[idx] = gpiod_chip_get_line(gpiod_chip[idx], adapter_gpio_config[idx].gpio_num); +- if (!gpiod_line[idx]) { +- LOG_ERROR("Error get line %s", adapter_gpio_get_name(idx)); ++ gpiod_line_settings[idx] = gpiod_line_settings_new(); ++ gpiod_line_config[idx] = gpiod_line_config_new(); ++ req_cfg = gpiod_request_config_new(); ++ ++ if (!gpiod_line_settings[idx] || !gpiod_line_config[idx] || !req_cfg) { ++ LOG_ERROR("Cannot configure LinuxGPIOD line for %s", adapter_gpio_get_name(idx)); ++ gpiod_request_config_free(req_cfg); + return ERROR_JTAG_INIT_FAILED; + } + ++ gpiod_request_config_set_consumer(req_cfg, "OpenOCD"); ++ + switch (adapter_gpio_config[idx].init_state) { + case ADAPTER_GPIO_INIT_STATE_INPUT: +- dir = GPIOD_LINE_REQUEST_DIRECTION_INPUT; ++ rv = gpiod_line_settings_set_direction(gpiod_line_settings[idx], GPIOD_LINE_DIRECTION_INPUT); + break; + case ADAPTER_GPIO_INIT_STATE_INACTIVE: +- dir = GPIOD_LINE_REQUEST_DIRECTION_OUTPUT; +- val = 0; ++ rv = gpiod_line_settings_set_direction(gpiod_line_settings[idx], GPIOD_LINE_DIRECTION_OUTPUT); ++ rv |= gpiod_line_settings_set_output_value(gpiod_line_settings[idx], GPIOD_LINE_VALUE_INACTIVE); + break; + case ADAPTER_GPIO_INIT_STATE_ACTIVE: +- dir = GPIOD_LINE_REQUEST_DIRECTION_OUTPUT; +- val = 1; ++ rv = gpiod_line_settings_set_direction(gpiod_line_settings[idx], GPIOD_LINE_DIRECTION_OUTPUT); ++ rv |= gpiod_line_settings_set_output_value(gpiod_line_settings[idx], GPIOD_LINE_VALUE_ACTIVE); + break; + } ++ if (rv < 0) { ++ LOG_ERROR("Error while configuring LinuxGPIOD line init state for %s", adapter_gpio_get_name(idx)); ++ gpiod_request_config_free(req_cfg); ++ return ERROR_JTAG_INIT_FAILED; ++ } + + switch (adapter_gpio_config[idx].drive) { + case ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL: ++ rv = gpiod_line_settings_set_drive(gpiod_line_settings[idx], GPIOD_LINE_DRIVE_PUSH_PULL); + break; + case ADAPTER_GPIO_DRIVE_MODE_OPEN_DRAIN: +- flags |= GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN; ++ rv = gpiod_line_settings_set_drive(gpiod_line_settings[idx], GPIOD_LINE_DRIVE_OPEN_DRAIN); + break; + case ADAPTER_GPIO_DRIVE_MODE_OPEN_SOURCE: +- flags |= GPIOD_LINE_REQUEST_FLAG_OPEN_SOURCE; ++ rv = gpiod_line_settings_set_drive(gpiod_line_settings[idx], GPIOD_LINE_DRIVE_OPEN_SOURCE); + break; + } ++ if (rv < 0) { ++ LOG_ERROR("Error while configuring LinuxGPIOD line driving for %s", adapter_gpio_get_name(idx)); ++ gpiod_request_config_free(req_cfg); ++ return ERROR_JTAG_INIT_FAILED; ++ } + + switch (adapter_gpio_config[idx].pull) { + case ADAPTER_GPIO_PULL_NONE: +-#ifdef GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE +- flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE; +-#endif ++ rv = gpiod_line_settings_set_bias(gpiod_line_settings[idx], GPIOD_LINE_BIAS_DISABLED); + break; + case ADAPTER_GPIO_PULL_UP: +-#ifdef GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP +- flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP; +-#else +- LOG_WARNING("linuxgpiod: ignoring request for pull-up on %s: not supported by gpiod v%s", +- adapter_gpio_get_name(idx), gpiod_version_string()); +-#endif ++ rv = gpiod_line_settings_set_bias(gpiod_line_settings[idx], GPIOD_LINE_BIAS_PULL_UP); + break; + case ADAPTER_GPIO_PULL_DOWN: +-#ifdef GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN +- flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN; +-#else +- LOG_WARNING("linuxgpiod: ignoring request for pull-down on %s: not supported by gpiod v%s", +- adapter_gpio_get_name(idx), gpiod_version_string()); +-#endif ++ rv = gpiod_line_settings_set_bias(gpiod_line_settings[idx], GPIOD_LINE_BIAS_PULL_DOWN); + break; + } ++ if (rv < 0) { ++ LOG_ERROR("Error while configuring LinuxGPIOD line biasing for %s", adapter_gpio_get_name(idx)); ++ gpiod_request_config_free(req_cfg); ++ return ERROR_JTAG_INIT_FAILED; ++ } + +- if (adapter_gpio_config[idx].active_low) +- flags |= GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW; ++ gpiod_line_settings_set_active_low(gpiod_line_settings[idx], adapter_gpio_config[idx].active_low); + +- struct gpiod_line_request_config config = { +- .consumer = "OpenOCD", +- .request_type = dir, +- .flags = flags, +- }; ++ rv = gpiod_line_config_add_line_settings(gpiod_line_config[idx], ++ (unsigned int *)&adapter_gpio_config[idx].gpio_num, 1, ++ gpiod_line_settings[idx]); ++ if (rv < 0) { ++ LOG_ERROR("Error configuring gpio line %s", adapter_gpio_get_name(idx)); ++ gpiod_request_config_free(req_cfg); ++ return ERROR_JTAG_INIT_FAILED; ++ } + +- retval = gpiod_line_request(gpiod_line[idx], &config, val); +- if (retval < 0) { ++ gpiod_line_req[idx] = gpiod_chip_request_lines(gpiod_chip[idx], req_cfg, gpiod_line_config[idx]); ++ ++ gpiod_request_config_free(req_cfg); ++ ++ if (!gpiod_line_req[idx]) { + LOG_ERROR("Error requesting gpio line %s", adapter_gpio_get_name(idx)); + return ERROR_JTAG_INIT_FAILED; + } +@@ -380,12 +703,12 @@ static int linuxgpiod_init(void) + goto out_error; + } + +- if (helper_get_line(ADAPTER_GPIO_IDX_TDO) != ERROR_OK || +- helper_get_line(ADAPTER_GPIO_IDX_TDI) != ERROR_OK || +- helper_get_line(ADAPTER_GPIO_IDX_TCK) != ERROR_OK || +- helper_get_line(ADAPTER_GPIO_IDX_TMS) != ERROR_OK || +- helper_get_line(ADAPTER_GPIO_IDX_TRST) != ERROR_OK) +- goto out_error; ++ if (helper_get_line(ADAPTER_GPIO_IDX_TDO) != ERROR_OK ++ || helper_get_line(ADAPTER_GPIO_IDX_TDI) != ERROR_OK ++ || helper_get_line(ADAPTER_GPIO_IDX_TCK) != ERROR_OK ++ || helper_get_line(ADAPTER_GPIO_IDX_TMS) != ERROR_OK ++ || helper_get_line(ADAPTER_GPIO_IDX_TRST) != ERROR_OK) ++ goto out_error; + } + + if (transport_is_swd()) { +@@ -415,9 +738,9 @@ static int linuxgpiod_init(void) + goto out_error; + } + +- if (helper_get_line(ADAPTER_GPIO_IDX_SRST) != ERROR_OK || +- helper_get_line(ADAPTER_GPIO_IDX_LED) != ERROR_OK) +- goto out_error; ++ if (helper_get_line(ADAPTER_GPIO_IDX_SRST) != ERROR_OK ++ || helper_get_line(ADAPTER_GPIO_IDX_LED) != ERROR_OK) ++ goto out_error; + + return ERROR_OK; +