diff options
Diffstat (limited to 'libntp/icom.c')
-rw-r--r-- | libntp/icom.c | 293 |
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 */ |