#include #include #include #include #include #include #include #include enum kiss_flags { KISS_NONE = 0x00, KISS_FRAME = 0x01, KISS_ESCAPE = 0x02 }; struct _patty_kiss_tnc { int fd; size_t size; size_t len; void * buf; }; patty_kiss_tnc *patty_kiss_tnc_open(const char *device, size_t bufsize) { patty_kiss_tnc *tnc; if ((tnc = malloc(sizeof(*tnc))) == NULL) { goto error_malloc_tnc; } if ((tnc->buf = malloc(bufsize)) == NULL) { goto error_malloc_buf; } if ((tnc->fd = open(device, O_RDWR)) < 0) { goto error_open; } tnc->size = bufsize; tnc->len = 0; return tnc; error_open: free(tnc->buf); error_malloc_buf: free(tnc); error_malloc_tnc: return NULL; } void patty_kiss_tnc_close(patty_kiss_tnc *tnc) { close(tnc->fd); free(tnc->buf); free(tnc); } ssize_t patty_kiss_read(patty_kiss_tnc *tnc, void **frame, int *port) { int flags = KISS_NONE; size_t i, b = 0; if (read(tnc->fd, tnc->buf, len) < 0) { goto error_io; } *port = 0; for (i=0; ibuf)[i]; if ((flags & KISS_FRAME) == 0) { if (c == PATTY_KISS_FEND) { flags |= KISS_FRAME; } continue; } if (flags & KISS_ESCAPE) { if (c == PATTY_KISS_TFEND) { ((unsigned char *)tnc->buf)[b++] = PATTY_KISS_FEND; } else if (c == PATTY_KISS_TFESC) { ((unsigned char *)tnc->buf)[b++] = PATTY_KISS_FESC; } else { errno = EIO; goto error_io; } flags &= ~KISS_ESCAPE; continue; } if (flags & KISS_FRAME) { if (c == PATTY_KISS_FESC) { flags |= KISS_ESCAPE; 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; } } return b + 1; error_io: return -1; } static inline ssize_t write_byte(int fd, unsigned char c) { return write(fd, &c, sizeof(c)); } 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) { 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) { goto error_io; } if (write_command(fd, PATTY_KISS_DATA, port) < 0) { goto error_io; } for (i=0; i