From bc10e0eb975d36607735de055d62a3878626c965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Fillod=2C=20F8CFE?= Date: Wed, 16 Jan 2002 22:56:34 +0000 Subject: [PATCH] parts moved from serial.[ch] git-svn-id: https://hamlib.svn.sourceforge.net/svnroot/hamlib/trunk@875 7ae35d74-ebe9-4afe-98af-79ac388436b8 --- src/iofunc.c | 332 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/iofunc.h | 35 ++++++ 2 files changed, 367 insertions(+) create mode 100644 src/iofunc.c create mode 100644 src/iofunc.h diff --git a/src/iofunc.c b/src/iofunc.c new file mode 100644 index 000000000..bcc475cdf --- /dev/null +++ b/src/iofunc.c @@ -0,0 +1,332 @@ +/* + * Hamlib Interface - generic file based io functions + * Copyright (c) 2000,2001,2002 by Stephane Fillod and Frank Singleton + * + * $Id: iofunc.c,v 1.1 2002-01-16 22:56:34 fillods Exp $ + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program 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 Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include /* Standard input/output definitions */ +#include /* String function definitions */ +#include /* UNIX standard function definitions */ +#include /* File control definitions */ +#include /* Error number definitions */ +#include +#include +#include +#include + +#include +#include "iofunc.h" +#include "misc.h" + + +/* + * Write a block of count characters to file descriptor, + * with a pause between each character if write_delay is > 0 + * + * The write_delay is for Yaesu type rigs..require 5 character + * sequence to be sent with 50-200msec between each char. + * + * Also, post_write_delay is for some Yaesu rigs (eg: FT747) that + * get confused with sequential fast writes between cmd sequences. + * + * + * + * input: + * + * fd - file descriptor to write to + * txbuffer - pointer to a command sequence array + * count - count of byte to send from the txbuffer + * write_delay - write delay in ms between 2 chars + * post_write_delay - minimum delay between two writes + * post_write_date - timeval of last write + * + * returns: + * + * 0 = OK + * <0 = NOT OK + * + * Actually, this function has nothing specific to serial comm, + * it could work very well also with any file handle, like a socket. + */ + +int write_block(port_t *p, const char *txbuffer, size_t count) +{ + int i; + +#ifdef WANT_NON_ACTIVE_POST_WRITE_DELAY + if (p->post_write_date.tv_sec != 0) { + signed int date_delay; /* in us */ + struct timeval tv; + + /* FIXME in Y2038 ... */ + gettimeofday(tv, NULL); + date_delay = p->post_write_delay*1000 - + ((tv.tv_sec - p->post_write_date->tv_sec)*1000000 + + (tv.tv_usec - p->post_write_date->tv_usec)); + if (date_delay > 0) { + /* + * optional delay after last write + */ + usleep(date_delay); + } + p->post_write_date.tv_sec = 0; + } +#endif + + if (p->write_delay > 0) { + for (i=0; i < count; i++) { + if (write(p->fd, txbuffer+i, 1) < 0) { + rig_debug(RIG_DEBUG_ERR,"write_block() failed - %s\n", + strerror(errno)); + return -RIG_EIO; + } + usleep(p->write_delay*1000); + } + } else { + write(p->fd, txbuffer, count); + } + + if (p->post_write_delay > 0) { +#ifdef WANT_NON_ACTIVE_POST_WRITE_DELAY +#define POST_WRITE_DELAY_TRSHLD 10 + + if (p->post_write_delay > POST_WRITE_DELAY_TRSHLD) + gettimeofday(p->post_write_date, NULL); + else +#else + usleep(p->post_write_delay*1000); /* optional delay after last write */ + /* otherwise some yaesu rigs get confused */ + /* with sequential fast writes*/ +#endif + } + rig_debug(RIG_DEBUG_TRACE,"TX %d bytes\n",count); + dump_hex(txbuffer,count); + + return RIG_OK; +} + + +/* + * Read "num" bytes from "fd" and put results into + * an array of unsigned char pointed to by "rxbuffer" + * + * Blocks on read until timeout hits. + * + * It then reads "num" bytes into rxbuffer. + * + * Actually, this function has nothing specific to serial comm, + * it could work very well also with any file handle, like a socket. + */ + +int read_block(port_t *p, char *rxbuffer, size_t count) +{ + fd_set rfds; + struct timeval tv, tv_timeout; + int rd_count, total_count = 0; + int retval; + + FD_ZERO(&rfds); + FD_SET(p->fd, &rfds); + + /* + * Wait up to timeout ms. + */ + tv_timeout.tv_sec = p->timeout/1000; + tv_timeout.tv_usec = (p->timeout%1000)*1000; + + while (count > 0) { + tv = tv_timeout; /* select may have updated it */ + + retval = select(p->fd+1, &rfds, NULL, NULL, &tv); + if (retval == 0) { + rig_debug(RIG_DEBUG_WARN, "read_block: timedout after %d chars\n", + total_count); + return -RIG_ETIMEOUT; + } + if (retval < 0) { + rig_debug(RIG_DEBUG_ERR,"read_block: select error after %d chars: " + "%s\n", total_count, strerror(errno)); + return -RIG_EIO; + } + + /* + * grab bytes from the rig + * The file descriptor must have been set up non blocking. + */ + rd_count = read(p->fd, rxbuffer+total_count, count); + if (rd_count < 0) { + rig_debug(RIG_DEBUG_ERR, "read_block: read failed - %s\n", + strerror(errno)); + return -RIG_EIO; + } + total_count += rd_count; + count -= rd_count; + } + + rig_debug(RIG_DEBUG_TRACE,"RX %d bytes\n",total_count); + dump_hex(rxbuffer, total_count); + return total_count; /* return bytes count read */ +} + +int fread_block(port_t *p, char *rxbuffer, size_t count) +{ + fd_set rfds; + struct timeval tv, tv_timeout; + int rd_count, total_count = 0; + int retval; + int fd; + + fd = fileno(p->stream); + + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + /* + * Wait up to timeout ms. + */ + tv_timeout.tv_sec = p->timeout/1000; + tv_timeout.tv_usec = (p->timeout%1000)*1000; + + + /* + * grab bytes from the rig + * The file descriptor must have been set up non blocking. + */ + rd_count = fread(rxbuffer, 1, count, p->stream); + if (rd_count < 0) { + rig_debug(RIG_DEBUG_ERR, "read_block: read failed - %s\n", + strerror(errno)); + return -RIG_EIO; + } + total_count += rd_count; + count -= rd_count; + + while (count > 0) { + tv = tv_timeout; /* select may have updated it */ + + retval = select(fd+1, &rfds, NULL, NULL, &tv); + if (retval == 0) { +#if 0 + rig_debug(RIG_DEBUG_WARN, "fread_block: timedout after %d chars\n", + total_count); +#endif + return -RIG_ETIMEOUT; + } + if (retval < 0) { + rig_debug(RIG_DEBUG_ERR,"fread_block: select error after %d chars: " + "%s\n", total_count, strerror(errno)); + return -RIG_EIO; + } + + /* + * grab bytes from the rig + * The file descriptor must have been set up non blocking. + */ + rd_count = fread(rxbuffer+total_count, 1, count, p->stream); + if (rd_count < 0) { + rig_debug(RIG_DEBUG_ERR, "read_block: read failed - %s\n", + strerror(errno)); + return -RIG_EIO; + } + total_count += rd_count; + count -= rd_count; + } + + rig_debug(RIG_DEBUG_TRACE,"RX %d bytes\n",total_count); + dump_hex(rxbuffer, total_count); + return total_count; /* return bytes count read */ +} + +/* + * Read a string from "fd" and put result into + * an array of unsigned char pointed to by "rxbuffer" + * + * Blocks on read until timeout hits. + * + * It then reads characters until one of the characters in + * "stopset" is found, or until "rxmax-1" characters was copied + * into rxbuffer. String termination character is added at the end. + * + * Actually, this function has nothing specific to serial comm, + * it could work very well also with any file handle, like a socket. + * + * Assumes rxbuffer!=NULL + */ +int read_string(port_t *p, char *rxbuffer, size_t rxmax, const char *stopset) +{ + fd_set rfds; + struct timeval tv, tv_timeout; + int rd_count, total_count = 0; + int retval; + + rxbuffer[0] = '\000'; + + FD_ZERO(&rfds); + FD_SET(p->fd, &rfds); + + /* + * Wait up to timeout ms. + */ + tv_timeout.tv_sec = p->timeout/1000; + tv_timeout.tv_usec = (p->timeout%1000)*1000; + + while (total_count < (rxmax-1)) { + tv = tv_timeout; /* select may have updated it */ + + retval = select(p->fd+1, &rfds, NULL, NULL, &tv); + if (retval == 0) /* Timed out */ + break; + + if (retval < 0) { + rig_debug(RIG_DEBUG_ERR,__FUNCTION__": select error after %d chars:" + " %s\n", total_count, strerror(errno)); + return -RIG_EIO; + } + /* + * read 1 character from the rig, (check if in stop set) + * The file descriptor must have been set up non blocking. + */ + rd_count = read(p->fd, &rxbuffer[total_count], 1); + if (rd_count < 0) { + rig_debug(RIG_DEBUG_ERR, __FUNCTION__": read failed - %s\n", + strerror(errno)); + return -RIG_EIO; + } + ++total_count; + if (stopset && strchr(stopset, rxbuffer[total_count-1])) + break; + /* Note: This function will always break on a '\000' character. */ + } + rxbuffer[total_count] = '\000'; + + if (total_count == 0) { + rig_debug(RIG_DEBUG_WARN, __FUNCTION__": timedout without reading a character\n"); + return -RIG_ETIMEOUT; + } + + rig_debug(RIG_DEBUG_TRACE,"RX %d characters\n",total_count); + dump_hex(rxbuffer, total_count); + return total_count; /* return bytes count read */ +} + diff --git a/src/iofunc.h b/src/iofunc.h new file mode 100644 index 000000000..77442c353 --- /dev/null +++ b/src/iofunc.h @@ -0,0 +1,35 @@ +/* + * Hamlib Interface - io function header + * Copyright (c) 2000,2001,2002 by Stephane Fillod and Frank Singleton + * + * $Id: iofunc.h,v 1.1 2002-01-16 22:56:34 fillods Exp $ + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program 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 Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _IOFUNC_H +#define _IOFUNC_H 1 + +#include + + +extern HAMLIB_EXPORT(int) read_block(port_t *p, char *rxbuffer, size_t count); +extern HAMLIB_EXPORT(int) write_block(port_t *p, const char *txbuffer, size_t count); +extern HAMLIB_EXPORT(int) fread_block(port_t *p, char *rxbuffer, size_t count); +extern HAMLIB_EXPORT(int) read_string(port_t *p, char *rxbuffer, size_t rxmax, const char *stopset); + +#endif /* _IOFUNC_H */ +