From 1bf736d650e2c4ceca3269d3b563aa951dd8b0ed Mon Sep 17 00:00:00 2001 From: Jeroen Vreeken Date: Sat, 28 May 2016 16:00:03 +0200 Subject: [PATCH] Add support for GPIO PTT. --- include/hamlib/rig.h | 12 +++++- src/Makefile.am | 2 +- src/gpio.c | 98 ++++++++++++++++++++++++++++++++++++++++++++ src/gpio.h | 38 +++++++++++++++++ src/rig.c | 39 ++++++++++++++++++ tests/rigctl.c | 4 ++ 6 files changed, 190 insertions(+), 3 deletions(-) create mode 100644 src/gpio.c create mode 100644 src/gpio.h diff --git a/include/hamlib/rig.h b/include/hamlib/rig.h index fb8fb456c..149b759b7 100644 --- a/include/hamlib/rig.h +++ b/include/hamlib/rig.h @@ -172,7 +172,9 @@ typedef enum rig_port_e { RIG_PORT_PARALLEL, /*!< Parallel port */ RIG_PORT_USB, /*!< USB port */ RIG_PORT_UDP_NETWORK, /*!< UDP Network socket type */ - RIG_PORT_CM108 /*!< CM108 GPIO */ + RIG_PORT_CM108, /*!< CM108 GPIO */ + RIG_PORT_GPIO, /*!< GPIO */ + RIG_PORT_GPION, /*!< GPIO inverted */ } rig_port_t; /** @@ -419,7 +421,9 @@ typedef enum { RIG_PTT_SERIAL_RTS, /*!< PTT control through serial RTS signal */ RIG_PTT_PARALLEL, /*!< PTT control through parallel port */ RIG_PTT_RIG_MICDATA, /*!< Legacy PTT (CAT PTT), supports RIG_PTT_ON_MIC/RIG_PTT_ON_DATA */ - RIG_PTT_CM108 /*!< PTT control through CM108 GPIO pin */ + RIG_PTT_CM108, /*!< PTT control through CM108 GPIO pin */ + RIG_PTT_GPIO, /*!< PTT control through GPIO pin */ + RIG_PTT_GPION, /*!< PTT control through inverted GPIO pin */ } ptt_type_t; /** @@ -1381,6 +1385,10 @@ typedef struct hamlib_port { char *vendor_name; /*!< Vendor name (opt.) */ char *product; /*!< Product (opt.) */ } usb; /*!< USB attributes */ + struct { + int on_value; + int value; + } gpio; } parm; /*!< Port parameter union */ } hamlib_port_t; diff --git a/src/Makefile.am b/src/Makefile.am index ca39ab9d1..c1668542e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,7 +4,7 @@ RIGSRC = rig.c serial.c serial.h misc.c misc.h register.c register.h event.c \ event.h cal.c cal.h conf.c tones.c tones.h rotator.c locator.c rot_reg.c \ rot_conf.c rot_conf.h iofunc.c iofunc.h ext.c mem.c settings.c \ parallel.c parallel.h usb_port.c usb_port.h debug.c network.c network.h \ - cm108.c cm108.h idx_builtin.h token.h par_nt.h + cm108.c cm108.h gpio.c gpio.h idx_builtin.h token.h par_nt.h lib_LTLIBRARIES = libhamlib.la libhamlib_la_SOURCES = $(RIGSRC) diff --git a/src/gpio.c b/src/gpio.c new file mode 100644 index 000000000..c69579d21 --- /dev/null +++ b/src/gpio.c @@ -0,0 +1,98 @@ +/* + * Hamlib Interface - gpio support + * Copyright (c) 2016 by Jeroen Vreeken + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "gpio.h" + +#include +#include +#include +#include +#include +#include + + +int gpio_open(hamlib_port_t *port, int on_value) +{ + char pathname[FILPATHLEN]; + FILE *fexp, *fdir; + int fd; + + port->parm.gpio.on_value = on_value; + + snprintf(pathname, FILPATHLEN, "/sys/class/gpio/export"); + fexp = fopen(pathname, "w"); + if (!fexp) { + rig_debug(RIG_DEBUG_ERR, "Export GPIO \"%s\": %s\n", port->pathname, strerror(errno)); + return -RIG_EIO; + } + fprintf(fexp, "%s\n", port->pathname); + fclose(fexp); + + snprintf(pathname, FILPATHLEN, "/sys/class/gpio/gpio%s/direction", port->pathname); + fdir = fopen(pathname, "w"); + if (!fdir) { + rig_debug(RIG_DEBUG_ERR, "GPIO\"%s\" direction: %s\n", port->pathname, strerror(errno)); + return -RIG_EIO; + } + fprintf(fdir, "out\n"); + fclose(fdir); + + snprintf(pathname, FILPATHLEN, "/sys/class/gpio/gpio%s/value", port->pathname); + fd = open(pathname, O_WRONLY); + if (fd < 0) { + rig_debug(RIG_DEBUG_ERR, "GPIO\"%s\" opening value file %s: %s\n", port->pathname, pathname, strerror(errno)); + return -RIG_EIO; + } + + port->fd = fd; + return fd; +} + +int gpio_close(hamlib_port_t *port) +{ + return close(port->fd); +} + +int gpio_ptt_set(hamlib_port_t *port, ptt_t pttx) +{ + char *val; + 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)) { + val = "1\n"; + } else { + val = "0\n"; + } + + if (write(port->fd, val, strlen(val)) <= 0) + return -RIG_EIO; + return RIG_OK; +} + +int gpio_ptt_get(hamlib_port_t *port, ptt_t *pttx) +{ + if (port->parm.gpio.value) + return RIG_PTT_ON; + else + return RIG_PTT_OFF; +} + diff --git a/src/gpio.h b/src/gpio.h new file mode 100644 index 000000000..c72a2b53f --- /dev/null +++ b/src/gpio.h @@ -0,0 +1,38 @@ +/* + * Hamlib Interface - gpio support header + * Copyright (c) 2016 by Jeroen Vreeken + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef _GPIO_H +#define _GPIO_H + +#include + + +__BEGIN_DECLS + +/* Hamlib internal use, see rig.c */ +int gpio_open(hamlib_port_t *p, int on_value); +int gpio_close(hamlib_port_t *p); +int gpio_ptt_set(hamlib_port_t *p, ptt_t pttx); +int gpio_ptt_get(hamlib_port_t *p, ptt_t *pttx); + +__END_DECLS + +#endif /* _GPIO_H */ diff --git a/src/rig.c b/src/rig.c index b5ad89210..9f0add53d 100644 --- a/src/rig.c +++ b/src/rig.c @@ -67,6 +67,7 @@ #include "network.h" #include "event.h" #include "cm108.h" +#include "gpio.h" /** * \brief Hamlib release number @@ -127,6 +128,7 @@ const char hamlib_copyright[231] = /* hamlib 1.2 ABI specifies 231 bytes */ #define DEFAULT_CM108_PTT_BITNUM 2 #endif +#define DEFAULT_GPIO_PORT "0" #define CHECK_RIG_ARG(r) (!(r) || !(r)->caps || !(r)->state.comm_state) @@ -331,6 +333,10 @@ RIG * HAMLIB_API rig_init(rig_model_t rig_model) strncpy(rs->rigport.pathname, DEFAULT_CM108_PORT, FILPATHLEN); rs->rigport.parm.cm108.ptt_bitnum = DEFAULT_CM108_PTT_BITNUM; break; + + case RIG_PORT_GPIO: + strncpy(rs->rigport.pathname, DEFAULT_GPIO_PORT, FILPATHLEN); + break; case RIG_PORT_NETWORK: case RIG_PORT_UDP_NETWORK: @@ -575,6 +581,24 @@ int HAMLIB_API rig_open(RIG *rig) else cm108_ptt_set(&rs->pttport, RIG_PTT_OFF); break; + case RIG_PTT_GPIO: + rs->pttport.fd = gpio_open(&rs->pttport, 1); + if (rs->pttport.fd < 0) { + rig_debug(RIG_DEBUG_ERR, + "Cannot open PTT device \"%s\"\n", + rs->pttport.pathname); + status = -RIG_EIO; + } else + gpio_ptt_set(&rs->pttport, RIG_PTT_OFF); + case RIG_PTT_GPION: + rs->pttport.fd = gpio_open(&rs->pttport, 0); + if (rs->pttport.fd < 0) { + rig_debug(RIG_DEBUG_ERR, + "Cannot open PTT device \"%s\"\n", + rs->pttport.pathname); + status = -RIG_EIO; + } else + gpio_ptt_set(&rs->pttport, RIG_PTT_OFF); default: rig_debug(RIG_DEBUG_ERR, "Unsupported PTT type %d\n", rs->pttport.type.ptt); @@ -727,6 +751,10 @@ int HAMLIB_API rig_close(RIG *rig) cm108_ptt_set(&rs->pttport, RIG_PTT_OFF); port_close(&rs->pttport, RIG_PORT_CM108); break; + case RIG_PTT_GPIO: + case RIG_PTT_GPION: + gpio_ptt_set(&rs->pttport, RIG_PTT_OFF); + port_close(&rs->pttport, RIG_PORT_GPIO); default: rig_debug(RIG_DEBUG_ERR, "Unsupported PTT type %d\n", rs->pttport.type.ptt); @@ -1302,6 +1330,10 @@ int HAMLIB_API rig_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt) case RIG_PTT_CM108: return cm108_ptt_set(&rig->state.pttport, ptt); + case RIG_PTT_GPIO: + case RIG_PTT_GPION: + return gpio_ptt_set(&rig->state.pttport, ptt); + case RIG_PTT_NONE: return -RIG_ENAVAIL; /* not available */ default: @@ -1393,6 +1425,13 @@ int HAMLIB_API rig_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt) return cm108_ptt_get(&rig->state.pttport, ptt); + case RIG_PTT_GPIO: + case RIG_PTT_GPION: + if (caps->get_ptt) + return caps->get_ptt(rig, vfo, ptt); + + return gpio_ptt_get(&rig->state.pttport, ptt); + case RIG_PTT_NONE: return -RIG_ENAVAIL; /* not available */ diff --git a/tests/rigctl.c b/tests/rigctl.c index 4c297b445..7eb7f331f 100644 --- a/tests/rigctl.c +++ b/tests/rigctl.c @@ -216,6 +216,10 @@ int main (int argc, char *argv[]) ptt_type = RIG_PTT_PARALLEL; else if (!strcmp(optarg, "CM108")) ptt_type = RIG_PTT_CM108; + else if (!strcmp(optarg, "GPIO")) + ptt_type = RIG_PTT_GPIO; + else if (!strcmp(optarg, "GPION")) + ptt_type = RIG_PTT_GPION; else if (!strcmp(optarg, "NONE")) ptt_type = RIG_PTT_NONE; else