diff --git a/configure.ac b/configure.ac index d07ec9b9a..3a6af4e55 100644 --- a/configure.ac +++ b/configure.ac @@ -529,6 +529,9 @@ AS_IF([test x"${cf_with_xml_support}" = "xyes"], [ AC_SUBST([LIBXML2_LIBS]) AC_SUBST([LIBXML2_CFLAGS]) +# TODO: I don't know how to use autoconf +LIBS="$LIBS -lgpiod" + ## ----------------- ## ## Language bindings ## diff --git a/include/hamlib/rig.h b/include/hamlib/rig.h index fc360c692..a03890f8e 100644 --- a/include/hamlib/rig.h +++ b/include/hamlib/rig.h @@ -2340,6 +2340,7 @@ typedef struct hamlib_port { int fd; /*!< File descriptor */ void *handle; /*!< handle for USB */ + void *gpio; /*!< handle for GPIO */ int write_delay; /*!< Delay between each byte sent out, in mS */ int post_write_delay; /*!< Delay between each commands send out, in mS */ diff --git a/src/gpio.c b/src/gpio.c index e5fcfb597..88bfd305f 100644 --- a/src/gpio.c +++ b/src/gpio.c @@ -19,135 +19,91 @@ * */ -#include -#include -#include -#include -#include -#include - #include "gpio.h" +#include +#include +#include +#include +#include +#include +#include + +#ifndef GPIOD_PATH +// This is what's used on the Raspberry Pi 4; I'm not sure about others +#define GPIO_CHIP_NAME "gpiochip0" +#endif + +#define GPIO_CHIP_CONSUMER "Hamlib" int gpio_open(hamlib_port_t *port, int output, int on_value) { - char pathname[HAMLIB_FILPATHLEN * 2]; - FILE *fexp, *fdir; - int fd; - char *dir; + struct gpiod_chip *chip; + struct gpiod_line *line; port->parm.gpio.on_value = on_value; - SNPRINTF(pathname, HAMLIB_FILPATHLEN, "/sys/class/gpio/export"); - fexp = fopen(pathname, "w"); + chip = gpiod_chip_open_by_name(GPIO_CHIP_NAME); - if (!fexp) + if (!chip) { - rig_debug(RIG_DEBUG_ERR, - "Export GPIO%s (using %s): %s\n", - port->pathname, - pathname, - strerror(errno)); + rig_debug(RIG_DEBUG_ERR, "Failed to open GPIO chip %s: %s\n", GPIO_CHIP_NAME, strerror(errno)); return -RIG_EIO; } - fprintf(fexp, "%s\n", port->pathname); - fclose(fexp); - - SNPRINTF(pathname, - sizeof(pathname), - "/sys/class/gpio/gpio%s/direction", - port->pathname); - fdir = fopen(pathname, "w"); - - if (!fdir) + line = gpiod_chip_get_line(chip, atoi(port->pathname)); + if (!line) { - rig_debug(RIG_DEBUG_ERR, - "GPIO%s direction (using %s): %s\n", - port->pathname, - pathname, - strerror(errno)); + rig_debug(RIG_DEBUG_ERR, "Failed to acquire GPIO%s: %s\n", port->pathname, strerror(errno)); + gpiod_chip_close(chip); return -RIG_EIO; } - dir = output ? "out" : "in"; - rig_debug(RIG_DEBUG_VERBOSE, "Setting direction of GPIO%s to %s\n", - port->pathname, dir); - fprintf(fdir, "%s\n", dir); - fclose(fdir); - - SNPRINTF(pathname, - sizeof(pathname), - "/sys/class/gpio/gpio%s/value", - port->pathname); - fd = open(pathname, O_RDWR); - - if (fd < 0) + if ((output && gpiod_line_request_output(line, GPIO_CHIP_CONSUMER, 0) < 0) || + (!output && gpiod_line_request_input(line, GPIO_CHIP_CONSUMER) < 0)) { - rig_debug(RIG_DEBUG_ERR, - "GPIO%s opening value file %s: %s\n", - port->pathname, - pathname, - strerror(errno)); + rig_debug(RIG_DEBUG_ERR, "Failed to set GPIO%s to %s mode: %s\n", + port->pathname, (output ? "OUTPUT" : "INPUT"), strerror(errno)); + gpiod_line_release(line); + gpiod_chip_close(chip); return -RIG_EIO; } - port->fd = fd; - return fd; + port->gpio = line; + + return RIG_OK; } - int gpio_close(hamlib_port_t *port) { - int retval; - char pathname[HAMLIB_FILPATHLEN * 2]; - FILE *fexp; - - retval = close(port->fd); - - SNPRINTF(pathname, HAMLIB_FILPATHLEN, "/sys/class/gpio/unexport"); - fexp = fopen(pathname, "w"); - - if (!fexp) - { - rig_debug(RIG_DEBUG_ERR, - "Export GPIO%s (using %s): %s\n", - port->pathname, - pathname, - strerror(errno)); - return -RIG_EIO; - } - - fprintf(fexp, "%s\n", port->pathname); - fclose(fexp); - return retval; + gpiod_line_close_chip((struct gpiod_line*)port->gpio); + return RIG_OK; } - int gpio_ptt_set(hamlib_port_t *port, ptt_t pttx) { - char *val; + int result = 0; port->parm.gpio.value = pttx != RIG_PTT_OFF; - if ((port->parm.gpio.value && port->parm.gpio.on_value) - || (!port->parm.gpio.value && !port->parm.gpio.on_value)) + if ((port->parm.gpio.value && port->parm.gpio.on_value) || + (!port->parm.gpio.value && !port->parm.gpio.on_value)) { - val = "1\n"; + result = gpiod_line_set_value((struct gpiod_line*)port->gpio, 1); } else { - val = "0\n"; + result = gpiod_line_set_value((struct gpiod_line*)port->gpio, 0); } - if (write(port->fd, val, strlen(val)) <= 0) + if (result) { + rig_debug(RIG_DEBUG_ERR, "Failed to set the value of GPIO%s: %s\n", port->pathname, strerror(errno)); return -RIG_EIO; } return RIG_OK; } - int gpio_ptt_get(hamlib_port_t *port, ptt_t *pttx) { if (port->parm.gpio.value) @@ -164,21 +120,15 @@ int gpio_ptt_get(hamlib_port_t *port, ptt_t *pttx) int gpio_dcd_get(hamlib_port_t *port, dcd_t *dcdx) { - char val; - int port_value; - - lseek(port->fd, 0, SEEK_SET); - - if (read(port->fd, &val, sizeof(val)) <= 0) + int val = gpiod_line_get_value((struct gpiod_line*)port->gpio); + if (val < 0) { - return -RIG_EIO; + rig_debug(RIG_DEBUG_ERR, "Failed to read the value of GPIO%s: %s\n", port->pathname, strerror(errno)); } rig_debug(RIG_DEBUG_VERBOSE, "DCD GPIO pin value: %c\n", val); - port_value = val - '0'; - - if (port_value == port->parm.gpio.on_value) + if (val == port->parm.gpio.on_value) { *dcdx = RIG_DCD_ON; }