summaryrefslogtreecommitdiffstats
path: root/kiss/mkiss.c
diff options
context:
space:
mode:
Diffstat (limited to 'kiss/mkiss.c')
-rw-r--r--kiss/mkiss.c256
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();