Skip to content

Commit

Permalink
Merge pull request #1792 from mhei/support-libgpiod-v1.4
Browse files Browse the repository at this point in the history
linuxgpio: add support for libgpiod v1.4
  • Loading branch information
mcuee committed Apr 28, 2024
2 parents db2580d + dceb55d commit 1848dea
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 24 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -217,11 +217,12 @@ jobs:
libftdi
readline
libserialport
pkg-config
- name: Configure
run: >-
cmake
-D CMAKE_C_FLAGS=-I/usr/local/include
-D CMAKE_EXE_LINKER_FLAGS=-L/usr/local/Cellar
-D CMAKE_C_FLAGS=-I/opt/homebrew/include
-D CMAKE_EXE_LINKER_FLAGS=-L/opt/homebrew/Cellar
-D DEBUG_CMAKE=1
-D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
-B build
Expand Down
35 changes: 27 additions & 8 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -240,23 +240,39 @@ 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)
# check whether we have version >= 2.0
pkg_check_modules(LIBGPIODV2 libgpiod>=2.0)
message(STATUS "Checking for module 'libgpiod'...")
pkg_check_modules(LIBGPIODV2 QUIET libgpiod>=2.0)
if(LIBGPIODV2_FOUND)
message(STATUS "Found module 'libgpiod' (found version \"${LIBGPIODV2_VERSION}\")")
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)
# check whether we have version >= 1.6
pkg_check_modules(LIBGPIODV1_6 QUIET libgpiod>=1.6)
if(LIBGPIODV1_6_FOUND)
message(STATUS "Found module 'libgpiod' (found version \"${LIBGPIODV1_6_VERSION}\")")
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 QUIET libgpiod)
if(LIBGPIOD_FOUND)
message(STATUS "Found module 'libgpiod' (found version \"${LIBGPIOD_VERSION}\")")
set(HAVE_LIBGPIOD 1)
set(CMAKE_REQUIRED_LIBRARIES ${LIBGPIOD_LIBRARIES})
set(LIB_LIBGPIOD ${LIBGPIOD_LINK_LIBRARIES})
else()
message(STATUS "Could not find module 'libgpiod', proceeding without.")
endif()
endif()
endif()
else()
Expand Down Expand Up @@ -358,6 +374,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()
Expand Down Expand Up @@ -429,9 +446,11 @@ endif()
if(HAVE_LINUXGPIO)
message(STATUS "ENABLED linuxgpio")
if (LIBGPIODV2_FOUND)
message(STATUS "DO HAVE libgpiod (v2.x)")
message(STATUS "DO HAVE libgpiod (${LIBGPIODV2_VERSION})")
elseif(LIBGPIODV1_6_FOUND)
message(STATUS "DO HAVE libgpiod (${LIBGPIODV1_6_VERSION})")
elseif(LIBGPIOD_FOUND)
message(STATUS "DO HAVE libgpiod")
message(STATUS "DO HAVE libgpiod (${LIBGPIOD_VERSION})")
else()
message(STATUS "DON'T HAVE libgpiod")
endif()
Expand Down
7 changes: 5 additions & 2 deletions src/cmake_config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
26 changes: 19 additions & 7 deletions src/configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -529,17 +529,27 @@ 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], [1], [Linux libgpiod available])
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
Expand Down Expand Up @@ -748,9 +758,11 @@ 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 < 2.0)"
elif test "x$have_libgpiod" = xyes; then
echo "DO HAVE libgpiod"
echo "DO HAVE libgpiod (< 1.6)"
else
echo "DON'T HAVE libgpiod"
fi
Expand Down
42 changes: 37 additions & 5 deletions src/linuxgpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -490,6 +506,14 @@ static inline int gpiod_line_get_value(struct gpiod_line *gpio_line) {

#endif

static inline unsigned int linuxgpio_get_gpio_num(struct gpiod_line *gpio_line) {
#if HAVE_LIBGPIOD_V2
return gpio_line->gpio_num;
#else
return gpiod_line_offset(gpio_line);
#endif
}

struct gpiod_line * linuxgpio_libgpiod_lines[N_PINS];

// Try to tell if libgpiod is going to work.
Expand Down Expand Up @@ -565,10 +589,14 @@ 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));
linuxgpio_get_gpio_num(linuxgpio_libgpiod_lines[i]), strerror(errno));
}
gpiod_line_release(linuxgpio_libgpiod_lines[i]);
linuxgpio_libgpiod_lines[i] = NULL;
Expand All @@ -577,10 +605,14 @@ 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));
linuxgpio_get_gpio_num(linuxgpio_libgpiod_lines[PIN_AVR_RESET]), strerror(errno));
}
gpiod_line_release(linuxgpio_libgpiod_lines[PIN_AVR_RESET]);
linuxgpio_libgpiod_lines[PIN_AVR_RESET] = NULL;
Expand All @@ -606,7 +638,7 @@ static int linuxgpio_libgpiod_setpin(const PROGRAMMER *pgm, int pinfunc, int val
int r = gpiod_line_set_value(linuxgpio_libgpiod_lines[pinfunc], value);
if (r != 0) {
msg_error("failed to set value of %s (%u) to %d: %s\n", avr_pin_name(pinfunc),
linuxgpio_libgpiod_lines[pinfunc]->gpio_num, value, strerror(errno));
linuxgpio_get_gpio_num(linuxgpio_libgpiod_lines[pinfunc]), value, strerror(errno));
return -1;
}

Expand All @@ -632,7 +664,7 @@ static int linuxgpio_libgpiod_getpin(const PROGRAMMER *pgm, int pinfunc) {

int r = gpiod_line_get_value(linuxgpio_libgpiod_lines[pinfunc]);
if (r == -1) {
msg_error("failed to read %u: %s\n", linuxgpio_libgpiod_lines[pinfunc]->gpio_num, strerror(errno));
msg_error("failed to read %u: %s\n", linuxgpio_get_gpio_num(linuxgpio_libgpiod_lines[pinfunc]), strerror(errno));
return -1;
}

Expand Down

0 comments on commit 1848dea

Please sign in to comment.