aboutsummaryrefslogtreecommitdiff
path: root/libntp/icom.c
diff options
context:
space:
mode:
Diffstat (limited to 'libntp/icom.c')
-rw-r--r--libntp/icom.c293
1 files changed, 66 insertions, 227 deletions
diff --git a/libntp/icom.c b/libntp/icom.c
index 280667eb4538..c981d8548418 100644
--- a/libntp/icom.c
+++ b/libntp/icom.c
@@ -5,6 +5,7 @@
* distribution. The only function provided is to load the radio
* frequency. All other parameters must be manually set before use.
*/
+#include <config.h>
#include "icom.h"
#include <unistd.h>
#include <stdio.h>
@@ -14,34 +15,47 @@
#include "ntp_tty.h"
#include "l_stdlib.h"
-/*
- * Scraps
- */
-#define BMAX 50 /* max command length */
-#define DICOM /dev/icom/ /* ICOM port link */
+#ifdef SYS_WINNT
+#undef write /* ports/winnt/include/config.h: #define write _write */
+extern int async_write(int, const void *, unsigned int);
+#define write(fd, data, octets) async_write(fd, data, octets)
+#endif
/*
- * FSA definitions
+ * Packet routines
+ *
+ * These routines send a packet and receive the response. If an error
+ * (collision) occurs on transmit, the packet is resent. If an error
+ * occurs on receive (timeout), all input to the terminating FI is
+ * discarded and the packet is resent. If the maximum number of retries
+ * is not exceeded, the program returns the number of octets in the user
+ * buffer; otherwise, it returns zero.
+ *
+ * ICOM frame format
+ *
+ * Frames begin with a two-octet preamble PR-PR followyd by the
+ * transceiver address RE, controller address TX, control code CN, zero
+ * or more data octets DA (depending on command), and terminator FI.
+ * Since the bus is bidirectional, every octet output is echoed on
+ * input. Every valid frame sent is answered with a frame in the same
+ * format, but with the RE and TX fields interchanged. The CN field is
+ * set to NAK if an error has occurred. Otherwise, the data are returned
+ * in this and following DA octets. If no data are returned, the CN
+ * octet is set to ACK.
+ *
+ * +------+------+------+------+------+--//--+------+
+ * | PR | PR | RE | TX | CN | DA | FI |
+ * +------+------+------+------+------+--//--+------+
*/
-#define S_IDLE 0 /* idle */
-#define S_HDR 1 /* header */
-#define S_TX 2 /* address */
-#define S_DATA 3 /* data */
-#define S_ERROR 4 /* error */
-
/*
- * Local function prototypes
+ * Scraps
*/
-static void doublefreq P((double, u_char *, int));
-static int sndpkt P((int, int, u_char *, u_char *));
-static int sndoctet P((int, int));
-static int rcvoctet P((int));
+#define DICOM /dev/icom/ /* ICOM port link */
/*
- * Local variables
+ * Local function prototypes
*/
-static int flags; /* trace flags */
-static int state; /* fsa state */
+static void doublefreq (double, u_char *, int);
/*
@@ -54,17 +68,18 @@ icom_freq( /* returns 0 (ok), EIO (error) */
double freq /* frequency (MHz) */
)
{
- u_char cmd[BMAX], rsp[BMAX];
+ u_char cmd[] = {PAD, PR, PR, 0, TX, V_SFREQ, 0, 0, 0, 0, FI,
+ FI};
int temp;
- cmd[0] = V_SFREQ;
+
+ cmd[3] = (char)ident;
if (ident == IC735)
temp = 4;
else
temp = 5;
- doublefreq(freq * 1e6, &cmd[1], temp);
- temp = sndpkt(fd, ident, cmd, rsp);
- if (temp < 1 || rsp[0] != ACK)
- return (EIO);
+ doublefreq(freq * 1e6, &cmd[6], temp);
+ temp = write(fd, cmd, temp + 7);
+
return (0);
}
@@ -80,10 +95,10 @@ doublefreq( /* returns void */
)
{
int i;
- char s1[11];
+ char s1[16];
char *y;
- sprintf(s1, " %10.0f", freq);
+ snprintf(s1, sizeof(s1), " %10.0f", freq);
y = s1 + 10;
i = 0;
while (*y != ' ') {
@@ -91,40 +106,13 @@ doublefreq( /* returns void */
x[i] = x[i] | ((*y-- & 0x0f) << 4);
i++;
}
- for (; i < len; i++)
+ for ( ; i < len; i++)
x[i] = 0;
x[i] = FI;
}
-
-/*
- * Packet routines
- *
- * These routines send a packet and receive the response. If an error
- * (collision) occurs on transmit, the packet is resent. If an error
- * occurs on receive (timeout), all input to the terminating FI is
- * discarded and the packet is resent. If the maximum number of retries
- * is not exceeded, the program returns the number of octets in the user
- * buffer; otherwise, it returns zero.
- *
- * ICOM frame format
- *
- * Frames begin with a two-octet preamble PR-PR followyd by the
- * transceiver address RE, controller address TX, control code CN, zero
- * or more data octets DA (depending on command), and terminator FI.
- * Since the bus is bidirectional, every octet output is echoed on
- * input. Every valid frame sent is answered with a frame in the same
- * format, but with the RE and TX fields interchanged. The CN field is
- * set to NAK if an error has occurred. Otherwise, the data are returned
- * in this and following DA octets. If no data are returned, the CN
- * octet is set to ACK.
- *
- * +------+------+------+------+------+--//--+------+
- * | PR | PR | RE | TX | CN | DA | FI |
- * +------+------+------+------+------+--//--+------+
- */
/*
- * icom_open() - open and initialize serial interface
+ * icom_init() - open and initialize serial interface
*
* This routine opens the serial interface for raw transmission; that
* is, character-at-a-time, no stripping, checking or monkeying with the
@@ -139,187 +127,38 @@ icom_init(
{
TTY ttyb;
int fd;
+ int flags;
+ int rc;
+ int saved_errno;
flags = trace;
- fd = open(device, O_RDWR, 0777);
+ fd = tty_open(device, O_RDWR, 0777);
if (fd < 0)
- return (fd);
-
- tcgetattr(fd, &ttyb);
+ return -1;
+
+ rc = tcgetattr(fd, &ttyb);
+ if (rc < 0) {
+ saved_errno = errno;
+ close(fd);
+ errno = saved_errno;
+ return -1;
+ }
ttyb.c_iflag = 0; /* input modes */
ttyb.c_oflag = 0; /* output modes */
- ttyb.c_cflag = IBAUD|CS8|CREAD|CLOCAL; /* control modes */
+ ttyb.c_cflag = IBAUD|CS8|CLOCAL; /* control modes (no read) */
ttyb.c_lflag = 0; /* local modes */
ttyb.c_cc[VMIN] = 0; /* min chars */
ttyb.c_cc[VTIME] = 5; /* receive timeout */
cfsetispeed(&ttyb, (u_int)speed);
cfsetospeed(&ttyb, (u_int)speed);
- tcsetattr(fd, TCSANOW, &ttyb);
- return (fd);
-}
-
-
-/*
- * sndpkt(r, x, y) - send packet and receive response
- *
- * This routine sends a command frame, which consists of all except the
- * preamble octets PR-PR. It then listens for the response frame and
- * returns the payload to the caller. The routine checks for correct
- * response header format; that is, the length of the response vector
- * returned to the caller must be at least 2 and the RE and TX octets
- * must be interchanged; otherwise, the operation is retried up to
- * the number of times specified in a global variable.
- *
- * The trace function, which is enabled by the P_TRACE bit of the global
- * flags variable, prints all characters received or echoed on the bus
- * preceded by a T (transmit) or R (receive). The P_ERMSG bit of the
- * flags variable enables printing of bus error messages.
- *
- * Note that the first octet sent is a PAD in order to allow time for
- * the radio to flush its receive buffer after sending the previous
- * response. Even with this precaution, some of the older radios
- * occasionally fail to receive a command and it has to be sent again.
- */
-static int
-sndpkt( /* returns octet count */
- int fd, /* file descriptor */
- int r, /* radio address */
- u_char *cmd, /* command vector */
- u_char *rsp /* response vector */
- )
-{
- int i, j, temp;
-
- (void)tcflush(fd, TCIOFLUSH);
- for (i = 0; i < RETRY; i++) {
- state = S_IDLE;
-
- /*
- * Transmit packet.
- */
- if (flags & P_TRACE)
- printf("icom T:");
- sndoctet(fd, PAD); /* send header */
- sndoctet(fd, PR);
- sndoctet(fd, PR);
- sndoctet(fd, r);
- sndoctet(fd, TX);
- for (j = 0; j < BMAX; j++) { /* send body */
- if (sndoctet(fd, cmd[j]) == FI)
- break;
- }
- while (rcvoctet(fd) != FI); /* purge echos */
- if (cmd[0] == V_FREQT || cmd[0] == V_MODET)
- return (0); /* shortcut for broadcast */
-
- /*
- * Receive packet. First, delete all characters
- * preceeding a PR, then discard all PRs. Check that the
- * RE and TX fields are correctly interchanged, then
- * copy the remaining data and FI to the user buffer.
- */
- if (flags & P_TRACE)
- printf("\nicom R:");
- j = 0;
- while ((temp = rcvoctet(fd)) != FI) {
- switch (state) {
-
- case S_IDLE:
- if (temp != PR)
- continue;
- state = S_HDR;
- break;
-
- case S_HDR:
- if (temp == PR) {
- continue;
- } else if (temp != TX) {
- if (flags & P_ERMSG)
- printf(
- "icom: TX error\n");
- state = S_ERROR;
- }
- state = S_TX;
- break;
-
- case S_TX:
- if (temp != r) {
- if (flags & P_ERMSG)
- printf(
- "icom: RE error\n");
- state = S_ERROR;
- }
- state = S_DATA;
- break;
-
- case S_DATA:
- if (j >= BMAX ) {
- if (flags & P_ERMSG)
- printf(
- "icom: buffer overrun\n");
- state = S_ERROR;
- j = 0;
- }
- rsp[j++] = (u_char)temp;
- break;
-
- case S_ERROR:
- break;
- }
- }
- if (flags & P_TRACE)
- printf("\n");
- if (j > 0) {
- rsp[j++] = FI;
- return (j);
- }
+ rc = tcsetattr(fd, TCSANOW, &ttyb);
+ if (rc < 0) {
+ saved_errno = errno;
+ close(fd);
+ errno = saved_errno;
+ return -1;
}
- if (flags & P_ERMSG)
- printf("icom: retries exceeded\n");
- return (0);
-}
-
-
-/*
- * Interface routines
- *
- * These routines read and write octets on the bus. In case of receive
- * timeout a FI code is returned. In case of output collision (echo
- * does not match octet sent), the remainder of the collision frame
- * (including the trailing FI) is discarded.
- */
-/*
- * sndoctet(fd, x) - send octet
- */
-static int
-sndoctet( /* returns octet */
- int fd, /* file descriptor */
- int x /* octet */
- )
-{
- u_char y;
-
- y = (u_char)x;
- write(fd, &y, 1);
- return (x);
-}
-
-
-/*
- * rcvoctet(fd) - receive octet
- */
-static int
-rcvoctet( /* returns octet */
- int fd /* file descriptor */
- )
-{
- u_char y;
-
- if (read(fd, &y, 1) < 1)
- y = FI; /* come here if timeout */
- if (flags & P_TRACE && y != PAD)
- printf(" %02x", y);
- return (y);
+ return (fd);
}
/* end program */