diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-07-08 06:44:55 +0200 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-07-08 06:44:55 +0200 |
commit | 5f5d1604492ae15967f9d86f41fbeeedcae0ae2b (patch) | |
tree | bcecfd65dc578eabfaee10b1e039c467ac89d8b5 /kiss/mkiss.c | |
parent | 1b4023134b5ff6342301c8135b11df46546d2828 (diff) |
Import ax25-tools 0.0.3 from tarballax25-tools-0.0.3
Diffstat (limited to 'kiss/mkiss.c')
-rw-r--r-- | kiss/mkiss.c | 256 |
1 files changed, 184 insertions, 72 deletions
diff --git a/kiss/mkiss.c b/kiss/mkiss.c index 8621ce4..bfdb46d 100644 --- a/kiss/mkiss.c +++ b/kiss/mkiss.c @@ -30,6 +30,11 @@ * system logging. * * 1.06 23/11/96 Tomi Manninen - Added simple support for polled kiss. + * + * 1.07 12/24/97 Deti Fliegl - Added Flexnet/BayCom CRC mode with commandline + * parameter -f + * + * 1.08 xx/xx/99 Tom Mazouch - Adjustable poll interval */ #include <stdio.h> @@ -50,6 +55,9 @@ #include <config.h> +#define FLEX_CRC 2 +#define G8BPQ_CRC 1 + #define SIZE 4096 #define FEND 0300 /* Frame End (0xC0) */ @@ -57,6 +65,7 @@ #define TFEND 0334 /* Transposed Frame End (0xDC) */ #define TFESC 0335 /* Transposed Frame Escape (0xDD) */ +#define ACKREQ 0x0C #define POLL 0x0E /* @@ -69,21 +78,26 @@ static int crc_errors = 0; static int invalid_ports = 0; static int return_polls = 0; -static char *usage_string = "usage: mkiss [-p] [-c] [-h] [-l] [-s speed] [-v] ttyinterface pty ...\n"; +static char *usage_string = "usage: mkiss [-p interval] [-c] [-f] [-h] [-l] [-s speed] [-v] ttyinterface pty ...\n"; static int dump_report = FALSE; static int logging = FALSE; static int crcflag = FALSE; static int hwflag = FALSE; -static int pollflag = FALSE; +static int pollspeed = 0; + +/* CRC-stuff */ +typedef unsigned short int u16; +#define CRCTYP 0x20 +static u16 crctab[256]; struct iface { char *name; /* Interface name (/dev/???) */ int fd; /* File descriptor */ int escaped; /* FESC received? */ - unsigned char crc; /* Incoming frame crc */ + u16 crc; /* Incoming frame crc */ unsigned char obuf[SIZE]; /* TX buffer */ unsigned char *optr; /* Next byte to transmit */ unsigned int errors; /* KISS protocol error count */ @@ -94,6 +108,28 @@ struct iface unsigned long txbytes; /* TX bytes count */ }; +static void init_crc(void) +{ + short int i, j; + u16 accum, data; + + for (i = 0; i < 256; i++) { /* fill table with CRC of values... */ + accum = 0xffff; + data = i; + for (j = 0; j < 8; ++j) { + if ((data^accum) & 0x0001) + /* if msb of data^accum is TRUE */ + /* then shift and subtract poly */ + accum = (accum >> 1) ^ 0x8408; + else + /* otherwise: transparent shift */ + accum >>= 1; + data >>= 1; /* move up next bit for XOR */ + } + crctab[i] = accum; + } +} + static int poll(int fd, int ports) { char buffer[3]; @@ -111,60 +147,88 @@ static int poll(int fd, int ports) return 0; } +static int put_ubyte(unsigned char* s, u16* crc, unsigned char c, int usecrc) +{ + int len = 1; + + if (c == FEND) { + *s++ = FESC; + *s++ = TFEND; + len++; + } else { + *s++ = c; + if (c == FESC) { + *s++ = TFESC; + len++; + } + } + + switch (usecrc) { + case G8BPQ_CRC: + *crc ^= c; /* Adjust checksum */ + break; + case FLEX_CRC: + *crc = (*crc<<8)^crctab[(*crc>>8)^((u16)((c)&255))]; + break; + } + + return len; +} + static int kiss_tx(int fd, int port, unsigned char *s, int len, int usecrc) { unsigned char *ptr = obuf; - unsigned char c; - unsigned char crc = 0; - int first = TRUE; + unsigned char c, cmd; + u16 crc = 0; + int i; + + cmd = s[0] & 0x0F; /* Non-data frames don't get a checksum byte */ - if ((s[0] & 0x0F) != 0) + if (usecrc == G8BPQ_CRC && cmd != 0 && cmd != ACKREQ) usecrc = FALSE; - /* Allow for checksum byte */ - if (usecrc) - len++; - /* * Send an initial FEND character to flush out any * data that may have accumulated in the receiver * due to line noise. */ - *ptr++ = FEND; + if (usecrc == FLEX_CRC) { + crc = 0xffff; + ptr += put_ubyte(ptr, &crc, CRCTYP, usecrc); + c = *s++; + } else { + c = *s++; + c = (c & 0x0F) | (port << 4); + ptr += put_ubyte(ptr, &crc, c, usecrc); + } + /* * For each byte in the packet, send the appropriate * character sequence, according to the SLIP protocol. */ + for(i = 0; i < len - 1; i++) + ptr += put_ubyte(ptr, &crc, s[i], usecrc); - while (len-- > 0) { - c = *s++; - if (first) { /* Control byte */ - c = (c & 0x0F) | (port << 4); - first = FALSE; - } - if (usecrc) { - if (len == 0) /* Now past user data... */ - c = crc; /* ...time to encode cksum */ - else - crc ^= c; /* Adjust checksum */ - } - switch (c) { - case FEND: - *ptr++ = FESC; - *ptr++ = TFEND; - break; - case FESC: - *ptr++ = FESC; - *ptr++ = TFESC; - break; - default: - *ptr++ = c; - break; + /* + * Now the checksum... + */ + switch (usecrc) { + case G8BPQ_CRC: + c = crc & 0xFF; + ptr += put_ubyte(ptr, &crc, c, usecrc); + break; + case FLEX_CRC: + { + u16 u = crc; + ptr += put_ubyte(ptr, &crc, u / 256, usecrc); + ptr += put_ubyte(ptr, &crc, u & 255, usecrc); } + break; } + *ptr++ = FEND; return write(fd, obuf, ptr - obuf); } @@ -176,37 +240,62 @@ static int kiss_rx(struct iface *ifp, unsigned char c, int usecrc) switch (c) { case FEND: len = ifp->optr - ifp->obuf; + if (len != 0 && ifp->escaped) { /* protocol error... */ len = 0; /* ...drop frame */ ifp->errors++; } - if (len != 0 && (ifp->obuf[0] & 0x0F) != 0) { - /* - * Non-data frames don't have checksum. - */ - usecrc = 0; - if ((ifp->obuf[0] & 0x0F) == POLL) { - len = 0; /* drop returned polls */ - return_polls++; - } else - ifp->nondata++; - } - if (len != 0 && usecrc) { - if (ifp->crc != 0) { /* checksum failed... */ - len = 0; /* ...drop frame */ - crc_errors++; - } else - len--; /* delete checksum byte */ + + if (len != 0) { + switch (usecrc) { + case G8BPQ_CRC: + if ((ifp->obuf[0] & 0x0F) != 0) { + /* + * Non-data frames don't have checksum. + */ + usecrc = 0; + if ((ifp->obuf[0] & 0x0F) == POLL) { + /* drop returned polls */ + len = 0; + return_polls++; + } else + ifp->nondata++; + } else { + if ((ifp->crc & 0xFF) != 0) { + /* checksum failed... */ + /* ...drop frame */ + len = 0; + crc_errors++; + } else + /* delete checksum byte */ + len--; + } + break; + case FLEX_CRC: + if (len > 14 && ifp->crc == 0x7070) { + len -= 2; + *ifp->obuf = 0; + } else { + len = 0; + crc_errors++; + } + break; + } } + if (len != 0) { ifp->rxpackets++; ifp->rxbytes += len; } + /* * Clean up. */ ifp->optr = ifp->obuf; - ifp->crc = 0; + if (usecrc == FLEX_CRC) + ifp->crc = 0xffff; + else + ifp->crc = 0; ifp->escaped = FALSE; return len; case FESC: @@ -231,9 +320,20 @@ static int kiss_rx(struct iface *ifp, unsigned char c, int usecrc) } break; } + *ifp->optr++ = c; - if (usecrc) + + switch (usecrc) { + case G8BPQ_CRC: ifp->crc ^= c; + break; + case FLEX_CRC: + ifp->crc = (ifp->crc << 8) ^ crctab[(ifp->crc >> 8) ^ c]; + break; + default: + break; + } + return 0; } @@ -264,9 +364,14 @@ static void report(struct iface *tty, struct iface **pty, int numptys) syslog(LOG_INFO, "Hardware handshaking %sabled.", hwflag ? "en" : "dis"); syslog(LOG_INFO, "G8BPQ checksumming %sabled.", - crcflag ? "en" : "dis"); + crcflag == G8BPQ_CRC ? "en" : "dis"); + syslog(LOG_INFO, "FLEX checksumming %sabled.", + crcflag == FLEX_CRC ? "en" : "dis"); + syslog(LOG_INFO, "polling %sabled.", - pollflag ? "en" : "dis"); + pollspeed ? "en" : "dis"); + if (pollspeed) + syslog(LOG_INFO, "Poll interval %d00ms", pollspeed); syslog(LOG_INFO, "ttyinterface is %s (fd=%d)", tty->name, tty->fd); for (i = 0; i < numptys; i++) syslog(LOG_INFO, "pty%d is %s (fd=%d)", i, pty[i]->name, @@ -297,14 +402,17 @@ int main(int argc, char *argv[]) unsigned char *icp; int topfd; fd_set readfd; - struct timeval timeout; + struct timeval timeout, pollinterval; int retval, numptys, i, size, len; int speed = -1; - while ((size = getopt(argc, argv, "chlps:v")) != -1) { + while ((size = getopt(argc, argv, "cfhlp:s:v")) != -1) { switch (size) { case 'c': - crcflag = TRUE; + crcflag = G8BPQ_CRC; + break; + case 'f': + crcflag = FLEX_CRC; break; case 'h': hwflag = TRUE; @@ -313,7 +421,9 @@ int main(int argc, char *argv[]) logging = TRUE; break; case 'p': - pollflag = TRUE; + pollspeed = atoi(optarg); + pollinterval.tv_sec = pollspeed / 10; + pollinterval.tv_usec = (pollspeed % 10) * 100000L; break; case 's': speed = atoi(optarg); @@ -368,9 +478,13 @@ int main(int argc, char *argv[]) tty->name = argv[optind]; tty_raw(tty->fd, hwflag); - if (speed != -1) tty_speed(tty->fd, speed); + if (speed != -1 && !tty_speed(tty->fd, speed)) { + close(tty->fd); + return 1; + } tty->optr = tty->obuf; topfd = tty->fd; + /* * Make it block again... */ @@ -414,7 +528,7 @@ int main(int argc, char *argv[]) openlog("mkiss", LOG_PID, LOG_DAEMON); syslog(LOG_INFO, "starting"); } - + init_crc(); /* * Loop until an error occurs on a read. */ @@ -424,13 +538,11 @@ int main(int argc, char *argv[]) for (i = 0; i < numptys; i++) FD_SET(pty[i]->fd, &readfd); - if (pollflag) { - timeout.tv_sec = 1; - timeout.tv_usec = 0; - } + if (pollspeed) + timeout = pollinterval; errno = 0; - retval = select(topfd + 1, &readfd, NULL, NULL, pollflag ? &timeout : NULL); + retval = select(topfd + 1, &readfd, NULL, NULL, pollspeed ? &timeout : NULL); if (retval == -1) { if (dump_report) { @@ -445,9 +557,9 @@ int main(int argc, char *argv[]) } /* - * Timer expired. + * Timer expired - let's poll... */ - if (retval == 0 && pollflag) { + if (retval == 0 && pollspeed) { poll(tty->fd, numptys); continue; } @@ -469,7 +581,7 @@ int main(int argc, char *argv[]) pty[i]->txbytes += len; } else invalid_ports++; - if (pollflag) + if (pollspeed) poll(tty->fd, numptys); } } @@ -496,7 +608,7 @@ int main(int argc, char *argv[]) } } - end: +end: if (logging) closelog(); |