IT'S ALIVE\!
This commit is contained in:
parent
1ef84ca2b4
commit
9278eca7c3
3 changed files with 122 additions and 50 deletions
|
@ -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 */
|
||||
|
|
11
src/Makefile
11
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)
|
||||
|
|
153
src/kiss.c
153
src/kiss.c
|
@ -1,4 +1,5 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -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; i<len; i++) {
|
||||
unsigned char c = ((char *)tnc->buf)[i];
|
||||
/*
|
||||
* Ah, yes, the icky state machine wherein we unescape things off the wire
|
||||
* and whatnot.
|
||||
*/
|
||||
for (i=0, b=0; i<tnc->buflen; 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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue