diff --git a/include/patty/kiss.h b/include/patty/kiss.h index 28c22b4..9b4b7ae 100644 --- a/include/patty/kiss.h +++ b/include/patty/kiss.h @@ -31,10 +31,10 @@ patty_kiss_tnc *patty_kiss_tnc_open(const char *device, size_t bufsize); void patty_kiss_tnc_close(patty_kiss_tnc *tnc); -ssize_t patty_kiss_read(patty_kiss_tnc *tnc, - void **buf, int *port); +ssize_t patty_kiss_tnc_recv(patty_kiss_tnc *tnc, + void **frame, int *port); -ssize_t patty_kiss_write(patty_kiss_tnc *tnc, - const void *buf, size_t len, int port); +ssize_t patty_kiss_tnc_send(patty_kiss_tnc *tnc, + const void *frame, size_t len, int port); #endif /* _PATTY_KISS_H */ diff --git a/src/Makefile b/src/Makefile index 9dfe9c0..3603db3 100644 --- a/src/Makefile +++ b/src/Makefile @@ -8,9 +8,9 @@ CFLAGS = $(CGFLAGS) -fPIC -Wall -O2 -I$(INCLUDE_PATH) LDFLAGS = HEADERS = kiss.h ax25.h -OBJS = kiss.o +OBJS = kiss.o test.o -PROGRAM = +PROGRAM = test AR = $(CROSS)ar RANLIB = $(CROSS)ranlib @@ -20,10 +20,13 @@ LN = /bin/ln RMDIR = /bin/rmdir INSTALL = /usr/bin/install -all: $(OBJS) +all: $(PROGRAM) + +$(PROGRAM): $(OBJS) + $(CC) $(LDFLAGS) $(OBJS) -o $(PROGRAM) $(OBJS): %.o: %.c $(HEADERS_BUILD) $(CC) $(CFLAGS) -c $< clean: - $(RM) -f $(OBJS) + $(RM) -f $(PROGRAM) $(OBJS) diff --git a/src/kiss.c b/src/kiss.c index a10fd9f..bbae7b5 100644 --- a/src/kiss.c +++ b/src/kiss.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -16,32 +17,40 @@ enum kiss_flags { struct _patty_kiss_tnc { int fd; - size_t size; - size_t len; + void * frame; void * buf; + size_t bufsz; + size_t buflen; }; -patty_kiss_tnc *patty_kiss_tnc_open(const char *device, size_t bufsize) { +patty_kiss_tnc *patty_kiss_tnc_open(const char *device, size_t bufsz) { patty_kiss_tnc *tnc; if ((tnc = malloc(sizeof(*tnc))) == NULL) { goto error_malloc_tnc; } - if ((tnc->buf = malloc(bufsize)) == NULL) { + if ((tnc->buf = malloc(bufsz)) == NULL) { goto error_malloc_buf; } + if ((tnc->frame = malloc(bufsz)) == NULL) { + goto error_malloc_frame; + } + if ((tnc->fd = open(device, O_RDWR)) < 0) { goto error_open; } - tnc->size = bufsize; - tnc->len = 0; + tnc->bufsz = bufsz; + tnc->buflen = 0; return tnc; error_open: + free(tnc->frame); + +error_malloc_frame: free(tnc->buf); error_malloc_buf: @@ -53,36 +62,79 @@ error_malloc_tnc: void patty_kiss_tnc_close(patty_kiss_tnc *tnc) { close(tnc->fd); + free(tnc->frame); free(tnc->buf); free(tnc); } -ssize_t patty_kiss_read(patty_kiss_tnc *tnc, void **frame, int *port) { +ssize_t patty_kiss_tnc_recv(patty_kiss_tnc *tnc, void **frame, int *port) { + size_t fillsz = tnc->bufsz - tnc->buflen; + size_t i, b; int flags = KISS_NONE; - size_t i, b = 0; - if (read(tnc->fd, tnc->buf, len) < 0) { - goto error_io; + /* + * If the buffer needs to be filled, then fill it. + */ + if (fillsz) { + void *dest = ((unsigned char *)tnc->buf) + tnc->buflen; + ssize_t readlen; + + if ((readlen = read(tnc->fd, dest, fillsz)) < 0) { + errno = EIO; + + goto error_io; + } + + tnc->buflen += readlen; } + /* + * Initialize the frame to be returned to the caller. + */ + memset(tnc->frame, '\0', tnc->bufsz); + + /* + * The default port is always zero, unless a command byte issued from the + * TNC in the first byte of the frame body. + */ *port = 0; - for (i=0; ibuf)[i]; + /* + * Ah, yes, the icky state machine wherein we unescape things off the wire + * and whatnot. + */ + for (i=0, b=0; ibuflen; i++) { + unsigned char c = ((unsigned char *)tnc->buf)[i]; - if ((flags & KISS_FRAME) == 0) { - if (c == PATTY_KISS_FEND) { - flags |= KISS_FRAME; - } + /* + * Not all KISS TNCs will emit a type byte at the start of a frame + * to the host; if the low nybble has a value of zero, then presume + * the high nybble to be the radio port number from which the + * packet originated. + */ + if (i == 1 && (c & 0x0f) == 0) { + *port = (c & 0xf0) >> 4; continue; } + if ((flags & KISS_FRAME) == 0) { + if (c == PATTY_KISS_FEND) { + flags |= KISS_FRAME; + + continue; + } + + errno = EIO; + + goto error_io; + } + if (flags & KISS_ESCAPE) { if (c == PATTY_KISS_TFEND) { - ((unsigned char *)tnc->buf)[b++] = PATTY_KISS_FEND; + ((unsigned char *)tnc->frame)[b++] = PATTY_KISS_FEND; } else if (c == PATTY_KISS_TFESC) { - ((unsigned char *)tnc->buf)[b++] = PATTY_KISS_FESC; + ((unsigned char *)tnc->frame)[b++] = PATTY_KISS_FESC; } else { errno = EIO; @@ -100,28 +152,45 @@ ssize_t patty_kiss_read(patty_kiss_tnc *tnc, void **frame, int *port) { continue; } else if (c == PATTY_KISS_FEND) { - flags &= ~KISS_FRAME; - break; } - /* - * Not all KISS TNCs will emit a type byte at the start of a frame - * to the host; if the low nybble has a value of zero, then presume - * the high nybble to be the radio port number from which the - * packet originated. - */ - if ((c & 0x0f) == 0) { - *port = (c & 0xf0) >> 4; - - continue; - } - - ((unsigned char *)tnc->buf)[b++] = c; + ((unsigned char *)tnc->frame)[b++] = c; } } - return b + 1; + /* + * Return empty-handed if we do not have a fully book-ended frame. + */ + if ((flags & KISS_FRAME) == 0) { + *frame = NULL; + + errno = EIO; + + goto error_io; + } + + if (i) { + /* + * As we have indeed found a frame at this point, move everything from + * the buffer not processed up to this point, to the beginning of the + * buffer. + */ + memmove(tnc->buf, ((unsigned char *)tnc->buf) + i, tnc->buflen - i); + + /* + * And decrement the buffer length by the number of bytes already + * processed. + */ + tnc->buflen -= i; + } + + /* + * Set the output parameter to the frame buffer. + */ + *frame = tnc->frame; + + return b; error_io: return -1; @@ -135,17 +204,17 @@ static inline ssize_t write_command(int fd, int command, int port) { return write_byte(fd, ((port & 0x0f) << 4) | (command & 0x0f)); } -ssize_t patty_kiss_write(patty_kiss_tnc *tnc, const void *buf, size_t len, int port) { +ssize_t patty_kiss_tnc_send(patty_kiss_tnc *tnc, const void *buf, size_t len, int port) { size_t i, start = 0, end = 0; unsigned char escape_fend[2] = { PATTY_KISS_FESC, PATTY_KISS_TFEND }; unsigned char escape_fesc[2] = { PATTY_KISS_FESC, PATTY_KISS_TFESC }; - if (write_byte(fd, PATTY_KISS_FEND) < 0) { + if (write_byte(tnc->fd, PATTY_KISS_FEND) < 0) { goto error_io; } - if (write_command(fd, PATTY_KISS_DATA, port) < 0) { + if (write_command(tnc->fd, PATTY_KISS_DATA, port) < 0) { goto error_io; } @@ -165,7 +234,7 @@ ssize_t patty_kiss_write(patty_kiss_tnc *tnc, const void *buf, size_t len, int p default: { end = i; - if (write(fd, &c, 1) < 0) { + if (write(tnc->fd, &c, 1) < 0) { goto error_io; } @@ -174,11 +243,11 @@ ssize_t patty_kiss_write(patty_kiss_tnc *tnc, const void *buf, size_t len, int p } if (escape) { - if (write(fd, ((unsigned char *)buf) + start, end - start) < 0) { + if (write(tnc->fd, ((unsigned char *)buf) + start, end - start) < 0) { goto error_io; } - if (write(fd, escape, 2) < 0) { + if (write(tnc->fd, escape, 2) < 0) { goto error_io; } @@ -189,12 +258,12 @@ ssize_t patty_kiss_write(patty_kiss_tnc *tnc, const void *buf, size_t len, int p } if (end - start) { - if (write(fd, ((unsigned char *)buf) + start, end - start) < 0) { + if (write(tnc->fd, ((unsigned char *)buf) + start, end - start) < 0) { goto error_io; } } - if (write_byte(fd, PATTY_KISS_FEND) < 0) { + if (write_byte(tnc->fd, PATTY_KISS_FEND) < 0) { goto error_io; }