2000-10-01 14:24:47 +00:00
|
|
|
/*
|
2001-07-13 19:08:15 +00:00
|
|
|
* Hamlib Interface - serial communication low-level support
|
2013-05-06 21:47:56 +00:00
|
|
|
* Copyright (c) 2000-2013 by Stephane Fillod
|
2009-06-01 17:02:58 +00:00
|
|
|
* Copyright (c) 2000-2003 by Frank Singleton
|
2001-07-13 19:08:15 +00:00
|
|
|
* Parts of the PTT handling are derived from soundmodem, an excellent
|
|
|
|
* ham packet softmodem written by Thomas Sailer, HB9JNX.
|
2000-10-01 14:24:47 +00:00
|
|
|
*
|
|
|
|
*
|
2011-08-22 01:07:57 +00:00
|
|
|
* 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.
|
2001-02-11 23:16:07 +00:00
|
|
|
*
|
2011-08-22 01:07:57 +00:00
|
|
|
* This library is distributed in the hope that it will be useful,
|
2001-07-13 19:08:15 +00:00
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2011-08-22 01:07:57 +00:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
2001-02-11 23:16:07 +00:00
|
|
|
*
|
2011-08-22 01:07:57 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2001-07-13 19:08:15 +00:00
|
|
|
* License along with this library; if not, write to the Free Software
|
2011-08-22 01:07:57 +00:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
2000-10-01 14:24:47 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2006-10-15 00:27:52 +00:00
|
|
|
/**
|
|
|
|
* \addtogroup rig_internal
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Serial port IO
|
|
|
|
* \file serial.c
|
|
|
|
*/
|
|
|
|
|
2001-02-09 23:08:20 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
2017-10-05 02:32:08 +00:00
|
|
|
# include "config.h"
|
2001-02-09 23:08:20 +00:00
|
|
|
#endif
|
|
|
|
|
2000-10-01 14:24:47 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h> /* Standard input/output definitions */
|
|
|
|
#include <string.h> /* String function definitions */
|
|
|
|
#include <unistd.h> /* UNIX standard function definitions */
|
|
|
|
#include <fcntl.h> /* File control definitions */
|
|
|
|
#include <errno.h> /* Error number definitions */
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <unistd.h>
|
2020-03-15 20:32:46 +00:00
|
|
|
#include <ctype.h>
|
2017-10-05 02:32:08 +00:00
|
|
|
|
2003-04-16 22:33:18 +00:00
|
|
|
#ifdef HAVE_SYS_IOCTL_H
|
2017-10-05 02:32:08 +00:00
|
|
|
# include <sys/ioctl.h>
|
2003-04-16 22:33:18 +00:00
|
|
|
#endif
|
2000-10-01 14:24:47 +00:00
|
|
|
|
2002-09-08 22:45:16 +00:00
|
|
|
#ifdef HAVE_SYS_PARAM_H
|
2017-10-05 02:32:08 +00:00
|
|
|
# include <sys/param.h>
|
2002-09-08 22:45:16 +00:00
|
|
|
#endif
|
|
|
|
|
2001-02-14 01:09:57 +00:00
|
|
|
#ifdef HAVE_TERMIOS_H
|
2017-10-05 02:32:08 +00:00
|
|
|
# include <termios.h> /* POSIX terminal control definitions */
|
2002-09-05 18:20:30 +00:00
|
|
|
#else
|
2017-10-05 02:32:08 +00:00
|
|
|
# ifdef HAVE_TERMIO_H
|
|
|
|
# include <termio.h>
|
|
|
|
# else /* sgtty */
|
|
|
|
# ifdef HAVE_SGTTY_H
|
|
|
|
# include <sgtty.h>
|
|
|
|
# endif
|
|
|
|
# endif
|
2003-04-16 22:33:18 +00:00
|
|
|
#endif
|
2001-02-14 01:09:57 +00:00
|
|
|
|
2020-04-09 22:56:19 +00:00
|
|
|
//! @cond Doxygen_Suppress
|
2003-08-20 07:22:40 +00:00
|
|
|
#if defined(WIN32) && !defined(HAVE_TERMIOS_H)
|
2017-10-05 02:32:08 +00:00
|
|
|
# include "win32termios.h"
|
|
|
|
# define HAVE_TERMIOS_H 1 /* we have replacement */
|
2003-08-15 01:25:26 +00:00
|
|
|
#else
|
2017-10-05 02:32:08 +00:00
|
|
|
# define OPEN open
|
|
|
|
# define CLOSE close
|
|
|
|
# define IOCTL ioctl
|
2003-08-15 01:25:26 +00:00
|
|
|
#endif
|
2020-04-09 22:56:19 +00:00
|
|
|
//! @endcond
|
2003-08-15 01:25:26 +00:00
|
|
|
|
2000-10-08 21:46:09 +00:00
|
|
|
#include <hamlib/rig.h>
|
2000-10-01 14:24:47 +00:00
|
|
|
#include "serial.h"
|
|
|
|
#include "misc.h"
|
|
|
|
|
2001-02-09 23:08:20 +00:00
|
|
|
#ifdef HAVE_SYS_IOCCOM_H
|
2017-10-05 02:32:08 +00:00
|
|
|
# include <sys/ioccom.h>
|
2001-02-09 23:08:20 +00:00
|
|
|
#endif
|
|
|
|
|
2017-08-16 07:09:10 +00:00
|
|
|
#include "microham.h"
|
2017-08-05 14:09:12 +00:00
|
|
|
|
2017-09-21 15:55:21 +00:00
|
|
|
static int uh_ptt_fd = -1;
|
|
|
|
static int uh_radio_fd = -1;
|
|
|
|
|
2020-04-09 22:56:19 +00:00
|
|
|
//! @cond Doxygen_Suppress
|
2019-11-30 16:19:08 +00:00
|
|
|
typedef struct term_options_backup
|
|
|
|
{
|
2019-06-09 21:05:06 +00:00
|
|
|
int fd;
|
|
|
|
#if defined(HAVE_TERMIOS_H)
|
|
|
|
struct termios options;
|
|
|
|
#elif defined(HAVE_TERMIO_H)
|
|
|
|
struct termio options;
|
|
|
|
#elif defined(HAVE_SGTTY_H)
|
|
|
|
struct sgttyb sg;
|
|
|
|
#endif
|
|
|
|
struct term_options_backup *next;
|
|
|
|
} term_options_backup_t;
|
2020-04-09 22:56:19 +00:00
|
|
|
//! @endcond
|
2019-06-09 21:05:06 +00:00
|
|
|
static term_options_backup_t *term_options_backup_head = NULL;
|
|
|
|
|
2017-10-05 02:32:08 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* This function simply returns TRUE if the argument matches uh_radio_fd and
|
|
|
|
* is >= 0
|
|
|
|
*
|
|
|
|
* This function is only used in the WIN32 case and implements access "from
|
|
|
|
* outside" to uh_radio_fd.
|
|
|
|
*/
|
2020-04-09 22:56:19 +00:00
|
|
|
//! @cond Doxygen_Suppress
|
2017-10-05 02:32:08 +00:00
|
|
|
int is_uh_radio_fd(int fd)
|
|
|
|
{
|
2019-11-30 16:19:08 +00:00
|
|
|
if (uh_radio_fd >= 0 && uh_radio_fd == fd)
|
|
|
|
{
|
2021-02-27 05:38:15 +00:00
|
|
|
return 1;
|
2019-11-30 16:19:08 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-02-27 05:38:15 +00:00
|
|
|
return 0;
|
2019-11-30 16:19:08 +00:00
|
|
|
}
|
2017-09-21 15:55:21 +00:00
|
|
|
}
|
2020-04-09 22:56:19 +00:00
|
|
|
//! @endcond
|
2017-09-21 15:55:21 +00:00
|
|
|
|
2017-10-05 02:32:08 +00:00
|
|
|
|
2006-10-15 00:27:52 +00:00
|
|
|
/**
|
|
|
|
* \brief Open serial port using rig.state data
|
|
|
|
* \param rp port data structure (must spec port id eg /dev/ttyS1)
|
|
|
|
* \return RIG_OK or < 0 if error
|
2000-10-01 14:24:47 +00:00
|
|
|
*/
|
2017-08-05 14:09:12 +00:00
|
|
|
int HAMLIB_API serial_open(hamlib_port_t *rp)
|
|
|
|
{
|
2001-02-14 01:09:57 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
int fd; /* File descriptor for the port */
|
|
|
|
int err;
|
2000-10-01 14:24:47 +00:00
|
|
|
|
2021-02-15 05:46:05 +00:00
|
|
|
ENTERFUNC;
|
2000-10-01 14:24:47 +00:00
|
|
|
|
2017-10-05 02:32:08 +00:00
|
|
|
if (!rp)
|
|
|
|
{
|
2021-02-15 05:46:05 +00:00
|
|
|
RETURNFUNC(-RIG_EINVAL);
|
2017-08-05 14:09:12 +00:00
|
|
|
}
|
2011-08-22 01:07:57 +00:00
|
|
|
|
2021-02-15 05:46:05 +00:00
|
|
|
|
|
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: %s\n", __func__, rp->pathname);
|
2021-02-28 15:46:01 +00:00
|
|
|
|
2019-11-30 16:19:08 +00:00
|
|
|
if (!strncmp(rp->pathname, "uh-rig", 6))
|
|
|
|
{
|
2017-08-16 07:09:10 +00:00
|
|
|
/*
|
|
|
|
* If the pathname is EXACTLY "uh-rig", try to use a microHam device
|
|
|
|
* rather than a conventional serial port.
|
|
|
|
* The microHam devices ALWAYS use "no parity", and can either use no handshake
|
|
|
|
* or hardware handshake. Return with error if something else is requested.
|
|
|
|
*/
|
2019-11-30 16:19:08 +00:00
|
|
|
if (rp->parm.serial.parity != RIG_PARITY_NONE)
|
|
|
|
{
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(-RIG_EIO);
|
2017-08-16 07:09:10 +00:00
|
|
|
}
|
2019-11-30 16:19:08 +00:00
|
|
|
|
2017-08-16 07:09:10 +00:00
|
|
|
if ((rp->parm.serial.handshake != RIG_HANDSHAKE_HARDWARE) &&
|
2019-11-30 16:19:08 +00:00
|
|
|
(rp->parm.serial.handshake != RIG_HANDSHAKE_NONE))
|
|
|
|
{
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(-RIG_EIO);
|
2017-08-16 07:09:10 +00:00
|
|
|
}
|
2019-11-30 16:19:08 +00:00
|
|
|
|
2017-08-16 07:09:10 +00:00
|
|
|
/*
|
|
|
|
* Note that serial setup is also don in uh_open_radio.
|
|
|
|
* So we need to dig into serial_setup().
|
|
|
|
*/
|
2019-11-30 16:19:08 +00:00
|
|
|
fd = uh_open_radio(
|
|
|
|
rp->parm.serial.rate, // baud
|
|
|
|
rp->parm.serial.data_bits, // databits
|
|
|
|
rp->parm.serial.stop_bits, // stopbits
|
|
|
|
(rp->parm.serial.handshake == RIG_HANDSHAKE_HARDWARE)); // rtscts
|
|
|
|
|
|
|
|
if (fd == -1)
|
|
|
|
{
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(-RIG_EIO);
|
2017-08-16 07:09:10 +00:00
|
|
|
}
|
2019-11-30 16:19:08 +00:00
|
|
|
|
|
|
|
rp->fd = fd;
|
2017-08-16 07:09:10 +00:00
|
|
|
/*
|
|
|
|
* Remember the fd in a global variable. We can do read(), write() and select()
|
|
|
|
* on fd but whenever it is tried to do an ioctl(), we have to catch it
|
|
|
|
* (e.g. setting DTR or tcflush on this fd does not work)
|
|
|
|
* While this may look dirty, it is certainly easier and more efficient than
|
|
|
|
* to check whether fd corresponds to a serial line or a socket everywhere.
|
|
|
|
*
|
|
|
|
* CAVEAT: for WIN32, it might be necessary to use win_serial_read() instead
|
|
|
|
* of read() for serial lines in iofunc.c. Therefore, we have to
|
|
|
|
* export uh_radio_fd to iofunc.c because in the case of sockets,
|
|
|
|
* read() must be used also in the WIN32 case.
|
|
|
|
* This is why uh_radio_fd is declared globally in microham.h.
|
2020-11-29 04:34:15 +00:00
|
|
|
* Notes from Joe Subich about microham behavior
|
|
|
|
* Microham debug tags
|
|
|
|
* A-RX ; Asynchronous data received (data not responsive to any
|
|
|
|
* poll from host or Router) - Set AI0;
|
|
|
|
* H2-RX; Data received in response to poll from Host 2 poll (2nd CAT port).
|
|
|
|
* H2-TX; Data poll/command from Host 2 (2nd CAT Port)
|
|
|
|
* R-RX; Data received in response to poll by microHAM USB Device Router
|
|
|
|
* R-TX; Router poll
|
|
|
|
* Note: R-TX; and R-RX; data is not passed to Host ports.
|
|
|
|
* 1) Router only polls when it has not seen a poll for FA; FB; and IF;
|
|
|
|
* (or equivalent for other manufacturers) within its timeout period.
|
|
|
|
* 2) The results of router's polling are not passed to the Host/apps.
|
|
|
|
* 3) Router only polls when there is no activity from the applications.
|
2020-11-30 20:53:55 +00:00
|
|
|
* 4) Router is designed to be transparent as far as the applications
|
2020-11-29 04:34:15 +00:00
|
|
|
* are concerned. The only exception is when the user chooses to
|
|
|
|
* run two applications (CAT and 2nd CAT) at the same time and has
|
|
|
|
* "auto-information" or CI-V enabled. In that case asynchronous data
|
|
|
|
* from the transceiver will be returned to both applications.
|
2017-08-16 07:09:10 +00:00
|
|
|
*/
|
2019-11-30 16:19:08 +00:00
|
|
|
uh_radio_fd = fd;
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(RIG_OK);
|
2017-08-16 07:09:10 +00:00
|
|
|
}
|
2019-11-30 16:19:08 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
/*
|
|
|
|
* Open in Non-blocking mode. Watch for EAGAIN errors!
|
|
|
|
*/
|
|
|
|
fd = OPEN(rp->pathname, O_RDWR | O_NOCTTY | O_NDELAY);
|
2020-03-15 20:32:46 +00:00
|
|
|
|
2017-10-05 02:32:08 +00:00
|
|
|
if (fd == -1)
|
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
/* Could not open the port. */
|
|
|
|
rig_debug(RIG_DEBUG_ERR,
|
|
|
|
"%s: Unable to open %s - %s\n",
|
|
|
|
__func__,
|
|
|
|
rp->pathname,
|
|
|
|
strerror(errno));
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(-RIG_EIO);
|
2017-08-05 14:09:12 +00:00
|
|
|
}
|
2011-08-22 01:07:57 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
rp->fd = fd;
|
2011-08-22 01:07:57 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
err = serial_setup(rp);
|
2002-03-07 22:49:00 +00:00
|
|
|
|
2017-10-05 02:32:08 +00:00
|
|
|
if (err != RIG_OK)
|
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
CLOSE(fd);
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(err);
|
2017-08-05 14:09:12 +00:00
|
|
|
}
|
2019-11-30 16:19:08 +00:00
|
|
|
|
2019-04-02 13:49:56 +00:00
|
|
|
serial_flush(rp); // ensure nothing is there when we open
|
2020-08-18 22:13:02 +00:00
|
|
|
hl_usleep(50 * 1000); // give a little time for MicroKeyer to finish
|
2002-03-07 22:49:00 +00:00
|
|
|
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(RIG_OK);
|
2002-03-07 22:49:00 +00:00
|
|
|
}
|
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
|
2006-10-15 00:27:52 +00:00
|
|
|
/**
|
|
|
|
* \brief Set up Serial port according to requests in port
|
|
|
|
* \param rp
|
|
|
|
* \return RIG_OK or < 0
|
|
|
|
*/
|
2005-04-03 12:27:17 +00:00
|
|
|
int HAMLIB_API serial_setup(hamlib_port_t *rp)
|
2002-03-07 22:49:00 +00:00
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
int fd;
|
|
|
|
/* There's a lib replacement for termios under Mingw */
|
2004-10-02 20:37:24 +00:00
|
|
|
#if defined(HAVE_TERMIOS_H)
|
2017-08-05 14:09:12 +00:00
|
|
|
speed_t speed; /* serial comm speed */
|
2019-06-09 21:05:06 +00:00
|
|
|
struct termios options, orig_options;
|
2002-03-07 22:49:00 +00:00
|
|
|
#elif defined(HAVE_TERMIO_H)
|
2019-06-09 21:05:06 +00:00
|
|
|
struct termio options, orig_options;
|
2002-03-07 22:49:00 +00:00
|
|
|
#elif defined(HAVE_SGTTY_H)
|
2019-06-09 21:05:06 +00:00
|
|
|
struct sgttyb sg, orig_sg;
|
2002-03-07 22:49:00 +00:00
|
|
|
#else
|
2017-10-05 02:32:08 +00:00
|
|
|
# error "No term control supported!"
|
2002-03-07 22:49:00 +00:00
|
|
|
#endif
|
2019-06-09 21:05:06 +00:00
|
|
|
term_options_backup_t *term_backup = NULL;
|
2002-03-07 22:49:00 +00:00
|
|
|
|
2021-02-15 05:46:05 +00:00
|
|
|
ENTERFUNC;
|
2002-03-07 22:49:00 +00:00
|
|
|
|
2017-10-05 02:32:08 +00:00
|
|
|
if (!rp)
|
|
|
|
{
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(-RIG_EINVAL);
|
2017-08-05 14:09:12 +00:00
|
|
|
}
|
2002-03-07 22:49:00 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
fd = rp->fd;
|
2011-08-22 01:07:57 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
/*
|
|
|
|
* Get the current options for the port...
|
|
|
|
*/
|
2004-10-02 20:37:24 +00:00
|
|
|
#if defined(HAVE_TERMIOS_H)
|
2020-03-15 20:32:46 +00:00
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: tcgetattr\n", __func__);
|
2017-08-05 14:09:12 +00:00
|
|
|
tcgetattr(fd, &options);
|
2019-06-09 21:05:06 +00:00
|
|
|
memcpy(&orig_options, &options, sizeof(orig_options));
|
2001-02-14 01:09:57 +00:00
|
|
|
#elif defined(HAVE_TERMIO_H)
|
2020-03-15 20:32:46 +00:00
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: IOCTL TCGETA\n", __func__);
|
2017-08-05 14:09:12 +00:00
|
|
|
IOCTL(fd, TCGETA, &options);
|
2019-06-09 21:05:06 +00:00
|
|
|
memcpy(&orig_options, &options, sizeof(orig_options));
|
2017-08-05 14:09:12 +00:00
|
|
|
#else /* sgtty */
|
2020-03-15 20:32:46 +00:00
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: IOCTL TIOCGETP\n", __func__);
|
2017-08-05 14:09:12 +00:00
|
|
|
IOCTL(fd, TIOCGETP, &sg);
|
2019-06-09 21:05:06 +00:00
|
|
|
memcpy(&orig_sg, &sg, sizeof(orig_sg));
|
2001-02-14 01:09:57 +00:00
|
|
|
#endif
|
2002-01-22 21:17:55 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_CFMAKERAW
|
2017-08-05 14:09:12 +00:00
|
|
|
/* Set serial port to RAW mode by default. */
|
2020-03-15 20:32:46 +00:00
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: cfmakeraw\n", __func__);
|
2017-08-05 14:09:12 +00:00
|
|
|
cfmakeraw(&options);
|
2002-01-22 21:17:55 +00:00
|
|
|
#endif
|
2002-01-07 17:14:22 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
/*
|
|
|
|
* Set the baud rates to requested values
|
|
|
|
*/
|
2017-10-05 02:32:08 +00:00
|
|
|
switch (rp->parm.serial.rate)
|
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
case 150:
|
|
|
|
speed = B150; /* yikes... */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 300:
|
|
|
|
speed = B300; /* yikes... */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 600:
|
2009-05-18 18:39:59 +00:00
|
|
|
speed = B600;
|
2017-08-05 14:09:12 +00:00
|
|
|
break;
|
2010-09-17 14:46:16 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
case 1200:
|
|
|
|
speed = B1200;
|
|
|
|
break;
|
2000-10-01 14:24:47 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
case 2400:
|
|
|
|
speed = B2400;
|
|
|
|
break;
|
2000-10-01 14:24:47 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
case 4800:
|
|
|
|
speed = B4800;
|
|
|
|
break;
|
2000-10-01 14:24:47 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
case 9600:
|
|
|
|
speed = B9600;
|
|
|
|
break;
|
2000-10-01 14:24:47 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
case 19200:
|
|
|
|
speed = B19200;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 38400:
|
|
|
|
speed = B38400;
|
|
|
|
break;
|
2000-10-01 14:24:47 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
case 57600:
|
|
|
|
speed = B57600; /* cool.. */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 115200:
|
|
|
|
speed = B115200; /* awesome! */
|
|
|
|
break;
|
|
|
|
|
2020-08-11 03:46:08 +00:00
|
|
|
#ifdef B230400
|
2020-08-18 22:13:02 +00:00
|
|
|
|
2020-08-11 03:46:08 +00:00
|
|
|
case 230400:
|
|
|
|
speed = B230400; /* super awesome! */
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
default:
|
|
|
|
rig_debug(RIG_DEBUG_ERR,
|
|
|
|
"%s: unsupported rate specified: %d\n",
|
|
|
|
__func__,
|
|
|
|
rp->parm.serial.rate);
|
|
|
|
CLOSE(fd);
|
|
|
|
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(-RIG_ECONF);
|
2017-08-05 14:09:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO */
|
2020-08-11 03:36:55 +00:00
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: cfsetispeed=%d,0x%04x\n", __func__,
|
2020-11-18 22:31:09 +00:00
|
|
|
(int)rp->parm.serial.rate, (int)speed);
|
2017-08-05 14:09:12 +00:00
|
|
|
cfsetispeed(&options, speed);
|
2020-08-11 03:36:55 +00:00
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: cfsetospeed=%d,0x%04x\n", __func__,
|
2020-11-18 22:31:09 +00:00
|
|
|
(int)rp->parm.serial.rate, (int)speed);
|
2017-08-05 14:09:12 +00:00
|
|
|
cfsetospeed(&options, speed);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Enable the receiver and set local mode...
|
|
|
|
*/
|
|
|
|
options.c_cflag |= (CLOCAL | CREAD);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* close doesn't change modem signals
|
|
|
|
*/
|
|
|
|
options.c_cflag &= ~HUPCL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set data to requested values.
|
|
|
|
*
|
|
|
|
*/
|
2020-08-11 03:26:25 +00:00
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: data_bits=%d\n", __func__,
|
|
|
|
rp->parm.serial.data_bits);
|
|
|
|
|
2017-10-05 02:32:08 +00:00
|
|
|
switch (rp->parm.serial.data_bits)
|
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
case 7:
|
|
|
|
options.c_cflag &= ~CSIZE;
|
|
|
|
options.c_cflag |= CS7;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 8:
|
|
|
|
options.c_cflag &= ~CSIZE;
|
|
|
|
options.c_cflag |= CS8;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
rig_debug(RIG_DEBUG_ERR,
|
|
|
|
"%s: unsupported serial_data_bits specified: %d\n",
|
|
|
|
__func__,
|
|
|
|
rp->parm.serial.data_bits);
|
|
|
|
CLOSE(fd);
|
|
|
|
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(-RIG_ECONF);
|
2017-08-05 14:09:12 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set stop bits to requested values.
|
|
|
|
*
|
|
|
|
*/
|
2017-10-05 02:32:08 +00:00
|
|
|
switch (rp->parm.serial.stop_bits)
|
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
case 1:
|
|
|
|
options.c_cflag &= ~CSTOPB;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
options.c_cflag |= CSTOPB;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
rig_debug(RIG_DEBUG_ERR,
|
|
|
|
"%s: unsupported serial_stop_bits specified: %d\n",
|
|
|
|
__func__,
|
|
|
|
rp->parm.serial.stop_bits);
|
|
|
|
CLOSE(fd);
|
|
|
|
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(-RIG_ECONF);
|
2017-08-05 14:09:12 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set parity to requested values.
|
|
|
|
*
|
|
|
|
*/
|
2020-08-11 03:26:25 +00:00
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: parity=%d\n", __func__, rp->parm.serial.parity);
|
|
|
|
|
2017-10-05 02:32:08 +00:00
|
|
|
switch (rp->parm.serial.parity)
|
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
case RIG_PARITY_NONE:
|
|
|
|
options.c_cflag &= ~PARENB;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RIG_PARITY_EVEN:
|
|
|
|
options.c_cflag |= PARENB;
|
|
|
|
options.c_cflag &= ~PARODD;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RIG_PARITY_ODD:
|
|
|
|
options.c_cflag |= PARENB;
|
|
|
|
options.c_cflag |= PARODD;
|
|
|
|
break;
|
|
|
|
/* CMSPAR is not POSIX */
|
2010-10-26 19:31:09 +00:00
|
|
|
#ifdef CMSPAR
|
2017-08-05 14:09:12 +00:00
|
|
|
|
|
|
|
case RIG_PARITY_MARK:
|
|
|
|
options.c_cflag |= PARENB | CMSPAR;
|
|
|
|
options.c_cflag |= PARODD;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RIG_PARITY_SPACE:
|
|
|
|
options.c_cflag |= PARENB | CMSPAR;
|
|
|
|
options.c_cflag &= ~PARODD;
|
|
|
|
break;
|
2010-10-26 19:31:09 +00:00
|
|
|
#endif
|
2000-10-01 14:24:47 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
default:
|
|
|
|
rig_debug(RIG_DEBUG_ERR,
|
|
|
|
"%s: unsupported serial_parity specified: %d\n",
|
|
|
|
__func__,
|
|
|
|
rp->parm.serial.parity);
|
|
|
|
CLOSE(fd);
|
2000-10-01 14:24:47 +00:00
|
|
|
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(-RIG_ECONF);
|
2017-08-05 14:09:12 +00:00
|
|
|
break;
|
|
|
|
}
|
2000-10-01 14:24:47 +00:00
|
|
|
|
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
/*
|
|
|
|
* Set flow control to requested mode
|
|
|
|
*
|
|
|
|
*/
|
2017-10-05 02:32:08 +00:00
|
|
|
switch (rp->parm.serial.handshake)
|
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
case RIG_HANDSHAKE_NONE:
|
|
|
|
options.c_cflag &= ~CRTSCTS;
|
|
|
|
options.c_iflag &= ~IXON;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RIG_HANDSHAKE_XONXOFF:
|
|
|
|
options.c_cflag &= ~CRTSCTS;
|
|
|
|
options.c_iflag |= IXON; /* Enable Xon/Xoff software handshaking */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RIG_HANDSHAKE_HARDWARE:
|
|
|
|
options.c_cflag |= CRTSCTS; /* Enable Hardware handshaking */
|
|
|
|
options.c_iflag &= ~IXON;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
rig_debug(RIG_DEBUG_ERR,
|
|
|
|
"%s: unsupported flow_control specified: %d\n",
|
|
|
|
__func__,
|
|
|
|
rp->parm.serial.handshake);
|
|
|
|
CLOSE(fd);
|
|
|
|
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(-RIG_ECONF);
|
2017-08-05 14:09:12 +00:00
|
|
|
break;
|
|
|
|
}
|
2000-10-01 14:24:47 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
/*
|
|
|
|
* Choose raw input, no preprocessing please ..
|
|
|
|
*/
|
|
|
|
#if defined(HAVE_TERMIOS_H) || defined(HAVE_TERMIO_H)
|
|
|
|
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
|
2000-10-01 14:24:47 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
/*
|
|
|
|
* Choose raw output, no preprocessing please ..
|
|
|
|
*/
|
|
|
|
options.c_oflag &= ~OPOST;
|
2000-10-01 14:24:47 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
#else /* sgtty */
|
|
|
|
sg.sg_flags = RAW;
|
2001-02-14 01:09:57 +00:00
|
|
|
#endif
|
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
/*
|
Fix spelling errors
Fixed using the following command:
codespell --write-changes --summary --skip=*.m4 --ignore-words-list="develope,get's,quitt,setts,som,ue,vektor"
codespell --write-changes --summary --skip=aclocal.m4,lib --ignore-words-list="develope,get's,quitt,setts,som,ue,vektor"
Codespell home page: https://github.com/codespell-project/codespell
2020-07-24 07:02:12 +00:00
|
|
|
* VTIME in deciseconds, rp->timeout in milliseconds
|
2017-08-05 14:09:12 +00:00
|
|
|
*/
|
|
|
|
options.c_cc[VTIME] = (rp->timeout + 99) / 100;
|
|
|
|
options.c_cc[VMIN] = 1;
|
2001-02-14 01:09:57 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
/*
|
|
|
|
* Flush serial port
|
|
|
|
*/
|
|
|
|
tcflush(fd, TCIFLUSH);
|
2000-10-01 14:24:47 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
/*
|
|
|
|
* Finally, set the new options for the port...
|
|
|
|
*/
|
|
|
|
#if defined(HAVE_TERMIOS_H)
|
2000-10-01 14:24:47 +00:00
|
|
|
|
2020-03-15 20:32:46 +00:00
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: tcsetattr TCSANOW\n", __func__);
|
|
|
|
|
2017-10-05 02:32:08 +00:00
|
|
|
if (tcsetattr(fd, TCSANOW, &options) == -1)
|
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
rig_debug(RIG_DEBUG_ERR,
|
|
|
|
"%s: tcsetattr failed: %s\n",
|
|
|
|
__func__,
|
|
|
|
strerror(errno));
|
|
|
|
CLOSE(fd);
|
|
|
|
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(-RIG_ECONF); /* arg, so close! */
|
2017-08-05 14:09:12 +00:00
|
|
|
}
|
2011-08-22 01:07:57 +00:00
|
|
|
|
2001-02-14 01:09:57 +00:00
|
|
|
#elif defined(HAVE_TERMIO_H)
|
2017-08-05 14:09:12 +00:00
|
|
|
|
2020-03-15 20:32:46 +00:00
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: IOCTL TCSETA\n", __func__);
|
|
|
|
|
2017-10-05 02:32:08 +00:00
|
|
|
if (IOCTL(fd, TCSETA, &options) == -1)
|
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
rig_debug(RIG_DEBUG_ERR,
|
|
|
|
"%s: ioctl(TCSETA) failed: %s\n",
|
|
|
|
__func__,
|
|
|
|
strerror(errno));
|
|
|
|
CLOSE(fd);
|
|
|
|
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(-RIG_ECONF); /* arg, so close! */
|
2017-08-05 14:09:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
2017-10-05 02:32:08 +00:00
|
|
|
|
2020-03-15 20:32:46 +00:00
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: IOCTL TIOCSETP\n", __func__);
|
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
/* sgtty */
|
2017-10-05 02:32:08 +00:00
|
|
|
if (IOCTL(fd, TIOCSETP, &sg) == -1)
|
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
rig_debug(RIG_DEBUG_ERR,
|
|
|
|
"%s: ioctl(TIOCSETP) failed: %s\n",
|
|
|
|
__func__,
|
|
|
|
strerror(errno));
|
|
|
|
CLOSE(fd);
|
|
|
|
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(-RIG_ECONF); /* arg, so close! */
|
2017-08-05 14:09:12 +00:00
|
|
|
}
|
|
|
|
|
2001-02-14 01:09:57 +00:00
|
|
|
#endif
|
|
|
|
|
2019-06-09 21:05:06 +00:00
|
|
|
// Store a copy of the original options for this FD, to be restored on close.
|
|
|
|
term_backup = malloc(sizeof(term_options_backup_t));
|
|
|
|
term_backup-> fd = fd;
|
|
|
|
#if defined(HAVE_TERMIOS_H) || defined(HAVE_TERMIO_H)
|
|
|
|
memcpy(&term_backup->options, &orig_options, sizeof(orig_options));
|
|
|
|
#elif defined(HAVE_SGTTY_H)
|
|
|
|
memcpy(&term_backup->sg, &orig_sg, sizeof(orig_sg));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// insert at head of list
|
|
|
|
term_backup->next = term_options_backup_head;
|
|
|
|
term_options_backup_head = term_backup;
|
|
|
|
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(RIG_OK);
|
2000-10-01 14:24:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-10-15 00:27:52 +00:00
|
|
|
/**
|
|
|
|
* \brief Flush all characters waiting in RX buffer.
|
|
|
|
* \param p
|
|
|
|
* \return RIG_OK
|
2001-12-15 03:13:39 +00:00
|
|
|
*/
|
2017-08-05 14:09:12 +00:00
|
|
|
int HAMLIB_API serial_flush(hamlib_port_t *p)
|
2001-12-15 03:13:39 +00:00
|
|
|
{
|
2021-02-15 05:46:05 +00:00
|
|
|
ENTERFUNC;
|
2020-03-15 20:32:46 +00:00
|
|
|
|
2020-11-25 14:40:24 +00:00
|
|
|
if (p->fd == uh_ptt_fd || p->fd == uh_radio_fd || p->flushx)
|
2020-03-16 03:40:40 +00:00
|
|
|
{
|
|
|
|
unsigned char buf[32];
|
|
|
|
/*
|
|
|
|
* Catch microHam case:
|
|
|
|
* if fd corresponds to a microHam device drain the line
|
|
|
|
* (which is a socket) by reading until it is empty.
|
|
|
|
*/
|
2020-11-30 20:53:55 +00:00
|
|
|
int n, nbytes = 0;
|
2020-03-15 20:32:46 +00:00
|
|
|
|
2020-11-25 14:40:24 +00:00
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: flushing\n", __func__);
|
2017-08-05 14:09:12 +00:00
|
|
|
|
2020-03-16 03:40:40 +00:00
|
|
|
while ((n = read(p->fd, buf, 32)) > 0)
|
|
|
|
{
|
2020-11-25 14:40:24 +00:00
|
|
|
nbytes += n;
|
2020-03-16 03:40:40 +00:00
|
|
|
//int i;
|
2019-11-30 16:19:08 +00:00
|
|
|
|
2020-03-16 03:40:40 +00:00
|
|
|
//for (i = 0; i < n; ++i) { printf("0x%02x(%c) ", buf[i], isprint(buf[i]) ? buf[i] : '~'); }
|
2019-11-30 16:19:08 +00:00
|
|
|
|
2020-03-16 03:40:40 +00:00
|
|
|
/* do nothing */
|
|
|
|
}
|
2020-11-30 20:53:55 +00:00
|
|
|
|
2020-11-25 14:40:24 +00:00
|
|
|
rig_debug(RIG_DEBUG_TRACE, "read flushed %d bytes\n", nbytes);
|
2019-11-30 16:19:08 +00:00
|
|
|
|
2020-03-15 20:32:46 +00:00
|
|
|
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(RIG_OK);
|
2020-03-16 03:40:40 +00:00
|
|
|
}
|
2020-03-15 20:32:46 +00:00
|
|
|
|
2020-11-25 14:40:24 +00:00
|
|
|
rig_debug(RIG_DEBUG_VERBOSE, "tcflush%s\n", "");
|
2017-08-05 14:09:12 +00:00
|
|
|
tcflush(p->fd, TCIFLUSH);
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(RIG_OK);
|
2001-12-15 03:13:39 +00:00
|
|
|
}
|
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
|
2006-10-15 00:27:52 +00:00
|
|
|
/**
|
|
|
|
* \brief Open serial port
|
|
|
|
* \param p
|
|
|
|
* \return fd
|
|
|
|
*/
|
2005-04-03 12:27:17 +00:00
|
|
|
int ser_open(hamlib_port_t *p)
|
2001-06-02 17:56:37 +00:00
|
|
|
{
|
2017-08-16 07:09:10 +00:00
|
|
|
int ret;
|
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
|
|
|
|
|
2019-11-30 16:19:08 +00:00
|
|
|
if (!strncmp(p->pathname, "uh-rig", 6))
|
|
|
|
{
|
2017-08-16 07:09:10 +00:00
|
|
|
/*
|
|
|
|
* This should not happen: ser_open is only used for
|
|
|
|
* DTR-only serial ports (ptt_pathname != rig_pathname).
|
|
|
|
*/
|
2019-11-30 16:19:08 +00:00
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!strncmp(p->pathname, "uh-ptt", 6))
|
|
|
|
{
|
2017-08-16 07:09:10 +00:00
|
|
|
/*
|
|
|
|
* Use microHam device for doing PTT. Although a valid file
|
|
|
|
* descriptor is returned, it is not used for anything
|
|
|
|
* but must be remembered in a global variable:
|
|
|
|
* If it is tried later to set/unset DTR on this fd, we know
|
|
|
|
* that we cannot use ioctl and must rather call our
|
|
|
|
* PTT set/unset service routine.
|
|
|
|
*/
|
2019-11-30 16:19:08 +00:00
|
|
|
ret = uh_open_ptt();
|
|
|
|
uh_ptt_fd = ret;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-08-16 07:09:10 +00:00
|
|
|
/*
|
|
|
|
* pathname is not uh_rig or uh_ptt: simply open()
|
|
|
|
*/
|
2020-09-30 17:57:31 +00:00
|
|
|
ret = OPEN(p->pathname, O_RDWR | O_NOCTTY | O_NDELAY);
|
2017-08-16 07:09:10 +00:00
|
|
|
}
|
|
|
|
}
|
2019-11-30 16:19:08 +00:00
|
|
|
|
|
|
|
p->fd = ret;
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(ret);
|
2001-06-02 17:56:37 +00:00
|
|
|
}
|
2001-02-09 23:08:20 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
|
2006-10-15 00:27:52 +00:00
|
|
|
/**
|
|
|
|
* \brief Close serial port
|
|
|
|
* \param p fd
|
|
|
|
* \return RIG_OK or < 0
|
|
|
|
*/
|
2005-04-03 12:27:17 +00:00
|
|
|
int ser_close(hamlib_port_t *p)
|
2001-02-09 23:08:20 +00:00
|
|
|
{
|
2017-08-16 07:09:10 +00:00
|
|
|
int rc;
|
2019-06-09 21:05:06 +00:00
|
|
|
term_options_backup_t *term_backup, *term_backup_prev;
|
2017-08-16 07:09:10 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
|
|
|
|
|
2017-08-16 07:09:10 +00:00
|
|
|
/*
|
|
|
|
* For microHam devices, do not close the
|
|
|
|
* socket via close but call a service routine
|
|
|
|
* (which might decide to keep the socket open).
|
|
|
|
* However, unset p->fd and uh_ptt_fd/uh_radio_fd.
|
|
|
|
*/
|
2019-11-30 16:19:08 +00:00
|
|
|
if (p->fd == uh_ptt_fd)
|
|
|
|
{
|
2017-08-16 07:09:10 +00:00
|
|
|
uh_close_ptt();
|
2019-11-30 16:19:08 +00:00
|
|
|
uh_ptt_fd = -1;
|
2017-08-16 07:09:10 +00:00
|
|
|
p->fd = -1;
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(0);
|
2017-08-16 07:09:10 +00:00
|
|
|
}
|
2019-11-30 16:19:08 +00:00
|
|
|
|
|
|
|
if (p->fd == uh_radio_fd)
|
|
|
|
{
|
2017-08-16 07:09:10 +00:00
|
|
|
uh_close_radio();
|
2019-11-30 16:19:08 +00:00
|
|
|
uh_radio_fd = -1;
|
2017-08-16 07:09:10 +00:00
|
|
|
p->fd = -1;
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(0);
|
2017-08-16 07:09:10 +00:00
|
|
|
}
|
|
|
|
|
2019-06-09 21:05:06 +00:00
|
|
|
// Find backup termios options to restore before closing
|
|
|
|
term_backup = term_options_backup_head;
|
|
|
|
term_backup_prev = term_options_backup_head;
|
2019-11-30 16:19:08 +00:00
|
|
|
|
|
|
|
while (term_backup)
|
|
|
|
{
|
|
|
|
if (term_backup->fd == p->fd)
|
|
|
|
{
|
2019-06-09 21:05:06 +00:00
|
|
|
// Found matching. Remove from list
|
2019-11-30 16:19:08 +00:00
|
|
|
if (term_backup == term_options_backup_head)
|
|
|
|
{
|
2019-06-09 21:05:06 +00:00
|
|
|
term_options_backup_head = term_backup->next;
|
2019-11-30 16:19:08 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-06-09 21:05:06 +00:00
|
|
|
term_backup_prev->next = term_backup->next;
|
|
|
|
}
|
2019-11-30 16:19:08 +00:00
|
|
|
|
2019-06-09 21:05:06 +00:00
|
|
|
break;
|
|
|
|
}
|
2019-11-30 16:19:08 +00:00
|
|
|
|
2019-06-09 21:05:06 +00:00
|
|
|
term_backup_prev = term_backup;
|
|
|
|
term_backup = term_backup->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Restore backup termios
|
2019-11-30 16:19:08 +00:00
|
|
|
if (term_backup)
|
|
|
|
{
|
2019-06-09 21:05:06 +00:00
|
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: restoring options\n", __func__);
|
|
|
|
#if defined(HAVE_TERMIOS_H)
|
|
|
|
|
|
|
|
if (tcsetattr(p->fd, TCSANOW, &term_backup->options) == -1)
|
|
|
|
{
|
|
|
|
rig_debug(RIG_DEBUG_ERR,
|
2019-11-30 16:19:08 +00:00
|
|
|
"%s: tcsetattr restore failed: %s\n",
|
|
|
|
__func__,
|
|
|
|
strerror(errno));
|
2019-06-09 21:05:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#elif defined(HAVE_TERMIO_H)
|
|
|
|
|
|
|
|
if (IOCTL(p->fd, TCSETA, &term_backup->options) == -1)
|
|
|
|
{
|
|
|
|
rig_debug(RIG_DEBUG_ERR,
|
2019-11-30 16:19:08 +00:00
|
|
|
"%s: ioctl(TCSETA) restore failed: %s\n",
|
|
|
|
__func__,
|
|
|
|
strerror(errno));
|
2019-06-09 21:05:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
/* sgtty */
|
|
|
|
if (IOCTL(p->fd, TIOCSETP, &term_backup->sg) == -1)
|
|
|
|
{
|
|
|
|
rig_debug(RIG_DEBUG_ERR,
|
2019-11-30 16:19:08 +00:00
|
|
|
"%s: ioctl(TIOCSETP) restore failed: %s\n",
|
|
|
|
__func__,
|
|
|
|
strerror(errno));
|
2019-06-09 21:05:06 +00:00
|
|
|
}
|
2019-11-30 16:19:08 +00:00
|
|
|
|
2019-06-09 21:05:06 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
free(term_backup);
|
2019-11-30 16:19:08 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-01-22 14:26:03 +00:00
|
|
|
rig_debug(RIG_DEBUG_TRACE, "%s: no options for fd to restore\n", __func__);
|
2019-06-09 21:05:06 +00:00
|
|
|
}
|
|
|
|
|
2017-08-16 07:09:10 +00:00
|
|
|
rc = CLOSE(p->fd);
|
2017-08-05 14:09:12 +00:00
|
|
|
p->fd = -1;
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(rc);
|
2001-02-09 23:08:20 +00:00
|
|
|
}
|
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
|
2006-10-15 00:27:52 +00:00
|
|
|
/**
|
|
|
|
* \brief Set Request to Send (RTS) bit
|
|
|
|
* \param p
|
|
|
|
* \param state true/false
|
|
|
|
* \return RIG_OK or < 0
|
|
|
|
*/
|
2005-04-03 12:27:17 +00:00
|
|
|
int HAMLIB_API ser_set_rts(hamlib_port_t *p, int state)
|
2001-01-28 22:18:09 +00:00
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
unsigned int y = TIOCM_RTS;
|
|
|
|
int rc;
|
2004-08-01 23:13:17 +00:00
|
|
|
|
2021-02-15 05:46:05 +00:00
|
|
|
ENTERFUNC;
|
2017-08-05 14:09:12 +00:00
|
|
|
|
|
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: RTS=%d\n", __func__, state);
|
2014-11-24 00:18:48 +00:00
|
|
|
|
2017-08-16 07:09:10 +00:00
|
|
|
// ignore this for microHam ports
|
2019-11-30 16:19:08 +00:00
|
|
|
if (p->fd == uh_ptt_fd || p->fd == uh_radio_fd)
|
|
|
|
{
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(RIG_OK);
|
2017-08-16 07:09:10 +00:00
|
|
|
}
|
|
|
|
|
2003-08-25 22:35:55 +00:00
|
|
|
#if defined(TIOCMBIS) && defined(TIOCMBIC)
|
2017-08-05 14:09:12 +00:00
|
|
|
rc = IOCTL(p->fd, state ? TIOCMBIS : TIOCMBIC, &y);
|
2003-08-25 22:35:55 +00:00
|
|
|
#else
|
2017-08-05 14:09:12 +00:00
|
|
|
rc = IOCTL(p->fd, TIOCMGET, &y);
|
2020-05-27 10:19:30 +00:00
|
|
|
|
2017-10-05 02:32:08 +00:00
|
|
|
if (rc >= 0)
|
|
|
|
{
|
|
|
|
if (state)
|
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
y |= TIOCM_RTS;
|
2017-10-05 02:32:08 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
y &= ~TIOCM_RTS;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = IOCTL(p->fd, TIOCMSET, &y);
|
2014-11-24 00:51:12 +00:00
|
|
|
}
|
2017-08-05 14:09:12 +00:00
|
|
|
|
2003-02-23 22:36:30 +00:00
|
|
|
#endif
|
2017-08-05 14:09:12 +00:00
|
|
|
|
2017-10-05 02:32:08 +00:00
|
|
|
if (rc < 0)
|
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
rig_debug(RIG_DEBUG_ERR,
|
|
|
|
"%s: Cannot change RTS - %s\n",
|
|
|
|
__func__,
|
|
|
|
strerror(errno));
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(-RIG_EIO);
|
2014-11-24 00:51:12 +00:00
|
|
|
}
|
2017-08-05 14:09:12 +00:00
|
|
|
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(RIG_OK);
|
2003-02-23 22:36:30 +00:00
|
|
|
}
|
2001-01-28 22:18:09 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
|
2006-10-15 00:27:52 +00:00
|
|
|
/**
|
|
|
|
* \brief Get RTS bit
|
|
|
|
* \param p supposed to be &rig->state.rigport
|
|
|
|
* \param state non-NULL
|
2003-08-17 22:39:07 +00:00
|
|
|
*/
|
2005-04-03 12:27:17 +00:00
|
|
|
int HAMLIB_API ser_get_rts(hamlib_port_t *p, int *state)
|
2003-08-17 22:39:07 +00:00
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
int retcode;
|
|
|
|
unsigned int y;
|
|
|
|
|
2017-08-16 07:09:10 +00:00
|
|
|
// cannot do this for microHam ports
|
2019-11-30 16:19:08 +00:00
|
|
|
if (p->fd == uh_ptt_fd || p->fd == uh_radio_fd)
|
|
|
|
{
|
2021-03-15 22:51:22 +00:00
|
|
|
return (-RIG_ENIMPL);
|
2017-08-16 07:09:10 +00:00
|
|
|
}
|
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
retcode = IOCTL(p->fd, TIOCMGET, &y);
|
|
|
|
*state = (y & TIOCM_RTS) == TIOCM_RTS;
|
2004-10-02 20:18:16 +00:00
|
|
|
|
2021-03-15 22:51:22 +00:00
|
|
|
return (retcode < 0 ? -RIG_EIO : RIG_OK);
|
2003-08-17 22:39:07 +00:00
|
|
|
}
|
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
|
2006-10-15 00:27:52 +00:00
|
|
|
/**
|
|
|
|
* \brief Set Data Terminal Ready (DTR) bit
|
|
|
|
* \param p
|
|
|
|
* \param state true/false
|
|
|
|
* \return RIG_OK or < 0
|
|
|
|
*/
|
2005-04-03 12:27:17 +00:00
|
|
|
int HAMLIB_API ser_set_dtr(hamlib_port_t *p, int state)
|
2003-02-23 22:36:30 +00:00
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
unsigned int y = TIOCM_DTR;
|
|
|
|
int rc;
|
|
|
|
|
2021-02-15 05:46:05 +00:00
|
|
|
ENTERFUNC;
|
2004-08-01 23:13:17 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
rig_debug(RIG_DEBUG_VERBOSE, "%s: DTR=%d\n", __func__, state);
|
2014-11-24 00:18:48 +00:00
|
|
|
|
2017-08-16 07:09:10 +00:00
|
|
|
// silently ignore on microHam RADIO channel,
|
|
|
|
// but (un)set ptt on microHam PTT channel.
|
2019-11-30 16:19:08 +00:00
|
|
|
if (p->fd == uh_radio_fd)
|
|
|
|
{
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(RIG_OK);
|
2017-08-16 07:09:10 +00:00
|
|
|
}
|
2019-11-30 16:19:08 +00:00
|
|
|
|
|
|
|
if (p->fd == uh_ptt_fd)
|
|
|
|
{
|
2017-08-16 07:09:10 +00:00
|
|
|
uh_set_ptt(state);
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(RIG_OK);
|
2017-08-16 07:09:10 +00:00
|
|
|
}
|
|
|
|
|
2003-08-25 22:35:55 +00:00
|
|
|
#if defined(TIOCMBIS) && defined(TIOCMBIC)
|
2017-08-05 14:09:12 +00:00
|
|
|
rc = IOCTL(p->fd, state ? TIOCMBIS : TIOCMBIC, &y);
|
2003-08-25 22:35:55 +00:00
|
|
|
#else
|
2017-08-05 14:09:12 +00:00
|
|
|
rc = IOCTL(p->fd, TIOCMGET, &y);
|
|
|
|
|
2017-10-05 02:32:08 +00:00
|
|
|
if (rc >= 0)
|
|
|
|
{
|
|
|
|
if (state)
|
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
y |= TIOCM_DTR;
|
2017-10-05 02:32:08 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
y &= ~TIOCM_DTR;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = IOCTL(p->fd, TIOCMSET, &y);
|
2014-11-24 00:51:12 +00:00
|
|
|
}
|
2017-08-05 14:09:12 +00:00
|
|
|
|
2001-06-02 17:56:37 +00:00
|
|
|
#endif
|
2017-08-05 14:09:12 +00:00
|
|
|
|
2017-10-05 02:32:08 +00:00
|
|
|
if (rc < 0)
|
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
rig_debug(RIG_DEBUG_ERR,
|
|
|
|
"%s: Cannot change DTR - %s\n",
|
|
|
|
__func__,
|
|
|
|
strerror(errno));
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(-RIG_EIO);
|
2014-11-24 00:51:12 +00:00
|
|
|
}
|
2017-08-05 14:09:12 +00:00
|
|
|
|
2021-02-28 15:46:01 +00:00
|
|
|
RETURNFUNC(RIG_OK);
|
2003-02-23 22:36:30 +00:00
|
|
|
}
|
2001-02-09 23:08:20 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
|
2006-10-15 00:27:52 +00:00
|
|
|
/**
|
|
|
|
* \brief Get DTR bit
|
|
|
|
* \param p supposed to be &rig->state.rigport
|
|
|
|
* \param state non-NULL
|
|
|
|
*/
|
2005-04-03 12:27:17 +00:00
|
|
|
int HAMLIB_API ser_get_dtr(hamlib_port_t *p, int *state)
|
2003-08-17 22:39:07 +00:00
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
int retcode;
|
|
|
|
unsigned int y;
|
|
|
|
|
2017-08-16 07:09:10 +00:00
|
|
|
// cannot do this for the RADIO port, return PTT state for the PTT port
|
2019-11-30 16:19:08 +00:00
|
|
|
if (p->fd == uh_ptt_fd)
|
|
|
|
{
|
|
|
|
*state = uh_get_ptt();
|
2021-03-15 22:51:22 +00:00
|
|
|
return (RIG_OK);
|
2017-08-16 07:09:10 +00:00
|
|
|
}
|
2019-11-30 16:19:08 +00:00
|
|
|
|
|
|
|
if (p->fd == uh_radio_fd)
|
|
|
|
{
|
2021-03-15 22:51:22 +00:00
|
|
|
return (-RIG_ENIMPL);
|
2017-08-16 07:09:10 +00:00
|
|
|
}
|
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
retcode = IOCTL(p->fd, TIOCMGET, &y);
|
|
|
|
*state = (y & TIOCM_DTR) == TIOCM_DTR;
|
2004-10-02 20:18:16 +00:00
|
|
|
|
2021-03-15 22:51:22 +00:00
|
|
|
return (retcode < 0 ? -RIG_EIO : RIG_OK);
|
2003-08-17 22:39:07 +00:00
|
|
|
}
|
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
|
2006-10-15 00:27:52 +00:00
|
|
|
/**
|
|
|
|
* \brief Set Break
|
|
|
|
* \param p
|
|
|
|
* \param state (ignored?)
|
|
|
|
* \return RIG_OK or < 0
|
|
|
|
*/
|
2005-04-03 12:27:17 +00:00
|
|
|
int HAMLIB_API ser_set_brk(hamlib_port_t *p, int state)
|
2004-04-16 20:04:11 +00:00
|
|
|
{
|
2017-08-16 07:09:10 +00:00
|
|
|
// ignore this for microHam ports
|
2019-11-30 16:19:08 +00:00
|
|
|
if (p->fd == uh_ptt_fd || p->fd == uh_radio_fd)
|
|
|
|
{
|
2021-03-15 22:51:22 +00:00
|
|
|
return (RIG_OK);
|
2017-08-16 07:09:10 +00:00
|
|
|
}
|
|
|
|
|
2004-04-16 20:04:11 +00:00
|
|
|
#if defined(TIOCSBRK) && defined(TIOCCBRK)
|
2021-03-15 22:51:22 +00:00
|
|
|
return (IOCTL(p->fd, state ? TIOCSBRK : TIOCCBRK, 0) < 0 ?
|
|
|
|
-RIG_EIO : RIG_OK);
|
2004-04-16 20:04:11 +00:00
|
|
|
#else
|
2021-03-15 22:51:22 +00:00
|
|
|
return (-RIG_ENIMPL);
|
2004-04-16 20:04:11 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
|
2006-10-15 00:27:52 +00:00
|
|
|
/**
|
|
|
|
* \brief Get Carrier (CI?) bit
|
|
|
|
* \param p supposed to be &rig->state.rigport
|
|
|
|
* \param state non-NULL
|
2003-08-17 22:39:07 +00:00
|
|
|
*/
|
2005-04-03 12:27:17 +00:00
|
|
|
int HAMLIB_API ser_get_car(hamlib_port_t *p, int *state)
|
2003-08-17 22:39:07 +00:00
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
int retcode;
|
|
|
|
unsigned int y;
|
2003-08-17 22:39:07 +00:00
|
|
|
|
2017-08-16 07:09:10 +00:00
|
|
|
// cannot do this for microHam ports
|
2019-11-30 16:19:08 +00:00
|
|
|
if (p->fd == uh_ptt_fd || p->fd == uh_radio_fd)
|
|
|
|
{
|
2021-03-15 22:51:22 +00:00
|
|
|
return (-RIG_ENIMPL);
|
2017-08-16 07:09:10 +00:00
|
|
|
}
|
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
retcode = IOCTL(p->fd, TIOCMGET, &y);
|
|
|
|
*state = (y & TIOCM_CAR) == TIOCM_CAR;
|
|
|
|
|
2021-03-15 22:51:22 +00:00
|
|
|
return (retcode < 0 ? -RIG_EIO : RIG_OK);
|
2001-02-09 23:08:20 +00:00
|
|
|
}
|
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
|
2006-10-15 00:27:52 +00:00
|
|
|
/**
|
|
|
|
* \brief Get Clear to Send (CTS) bit
|
|
|
|
* \param p supposed to be &rig->state.rigport
|
|
|
|
* \param state non-NULL
|
|
|
|
*/
|
2005-04-03 12:27:17 +00:00
|
|
|
int HAMLIB_API ser_get_cts(hamlib_port_t *p, int *state)
|
2001-02-09 23:08:20 +00:00
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
int retcode;
|
|
|
|
unsigned int y;
|
|
|
|
|
2017-08-16 07:09:10 +00:00
|
|
|
// cannot do this for microHam ports
|
2019-11-30 16:19:08 +00:00
|
|
|
if (p->fd == uh_ptt_fd || p->fd == uh_radio_fd)
|
|
|
|
{
|
2021-03-15 22:51:22 +00:00
|
|
|
return (-RIG_ENIMPL);
|
2017-08-16 07:09:10 +00:00
|
|
|
}
|
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
retcode = IOCTL(p->fd, TIOCMGET, &y);
|
|
|
|
*state = (y & TIOCM_CTS) == TIOCM_CTS;
|
2001-02-09 23:08:20 +00:00
|
|
|
|
2021-03-15 22:51:22 +00:00
|
|
|
return (retcode < 0 ? -RIG_EIO : RIG_OK);
|
2001-02-09 23:08:20 +00:00
|
|
|
}
|
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
|
2006-10-15 00:27:52 +00:00
|
|
|
/**
|
|
|
|
* \brief Get Data Set Ready (DSR) bit
|
|
|
|
* \param p supposed to be &rig->state.rigport
|
|
|
|
* \param state non-NULL
|
|
|
|
*/
|
2005-04-03 12:27:17 +00:00
|
|
|
int HAMLIB_API ser_get_dsr(hamlib_port_t *p, int *state)
|
2001-02-09 23:08:20 +00:00
|
|
|
{
|
2017-08-05 14:09:12 +00:00
|
|
|
int retcode;
|
|
|
|
unsigned int y;
|
|
|
|
|
2017-08-16 07:09:10 +00:00
|
|
|
// cannot do this for microHam ports
|
2019-11-30 16:19:08 +00:00
|
|
|
if (p->fd == uh_ptt_fd || p->fd == uh_radio_fd)
|
|
|
|
{
|
2021-03-15 22:51:22 +00:00
|
|
|
return (-RIG_ENIMPL);
|
2017-08-16 07:09:10 +00:00
|
|
|
}
|
2019-11-30 16:19:08 +00:00
|
|
|
|
2017-08-05 14:09:12 +00:00
|
|
|
retcode = IOCTL(p->fd, TIOCMGET, &y);
|
|
|
|
*state = (y & TIOCM_DSR) == TIOCM_DSR;
|
2001-02-09 23:08:20 +00:00
|
|
|
|
2021-03-15 22:51:22 +00:00
|
|
|
return (retcode < 0 ? -RIG_EIO : RIG_OK);
|
2001-02-09 23:08:20 +00:00
|
|
|
}
|
|
|
|
|
2006-10-15 00:27:52 +00:00
|
|
|
/** @} */
|