Changes: * Implement patty_ax25_if_driver type, providing a vtable with pointers to methods implementing an AX.25 interface PHY * Implement patty_ax25_if_name() to return a pointer to the name string of an AX.25 interface * Decouple patty_kiss_tnc from src/if.c using patty_ax25_if_driver * Remove port input/output arguments from patty_kiss_tnc_send() and patty_kiss_tnc_recv(), respectively; use 0 as the default, but keep the port argument in patty_kiss_frame_send() * Implement patty_ax25_if_fd() to return file descriptor backing a PHY; use this rather than patty_kiss_tnc_fd() in src/server.c to further decouple interfaces from their implementation * Remove 'enum patty_ax25_if_type' type; refactor constructor patty_ax25_if_new() to no longer take this as an argument, but rather a patty_ax25_if_driver to use to instantiate the PHY with the information pointer passed * Break out patty_kiss_tnc code from src/kiss.c into src/tnc.c, leaving only patty_kiss_frame_send() in the original; this is needed to prevent a cyclic dependency within patty_ax25_sock and other areas * Rename patty_bin_if_config() to patty_bin_if_create(); a separate patty_bin_if_config() will likely be created later as necessary to change an existing interface * Split PHY-specific interface configuration code into separate delegates in bin/if.c * Implement usage of patty_error to better capture internal error states not currently representable with semantic error numbers while configuring and instantiating PHYs * Pass patty_error object to patty_bin_kiss_config() to receive detailed error information
94 lines
2.1 KiB
C
94 lines
2.1 KiB
C
#define _GNU_SOURCE
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <inttypes.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <termios.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/un.h>
|
|
#include <errno.h>
|
|
|
|
#include <patty/kiss.h>
|
|
|
|
#include "config.h"
|
|
|
|
static inline ssize_t write_byte(int fd, uint8_t c) {
|
|
return write(fd, &c, sizeof(c));
|
|
}
|
|
|
|
static inline ssize_t write_start(int fd,
|
|
enum patty_kiss_command command,
|
|
int port) {
|
|
uint8_t start[2] = {
|
|
PATTY_KISS_FEND,
|
|
((port & 0x0f) << 4) | (command & 0x0f)
|
|
};
|
|
|
|
return write(fd, start, sizeof(start));
|
|
}
|
|
|
|
static uint8_t escape_fend[2] = { PATTY_KISS_FESC, PATTY_KISS_TFEND };
|
|
static uint8_t escape_fesc[2] = { PATTY_KISS_FESC, PATTY_KISS_TFESC };
|
|
|
|
ssize_t patty_kiss_frame_send(int fd,
|
|
const void *buf,
|
|
size_t len,
|
|
int port) {
|
|
size_t i, start = 0, end = 0;
|
|
|
|
if (write_start(fd, PATTY_KISS_DATA, port) < 0) {
|
|
goto error_io;
|
|
}
|
|
|
|
for (i=0; i<len; i++) {
|
|
uint8_t c = ((uint8_t *)buf)[i];
|
|
uint8_t *escape = NULL;
|
|
|
|
switch (c) {
|
|
case PATTY_KISS_FEND:
|
|
escape = escape_fend;
|
|
break;
|
|
|
|
case PATTY_KISS_FESC:
|
|
escape = escape_fesc;
|
|
break;
|
|
|
|
default:
|
|
end = i + 1;
|
|
|
|
break;
|
|
}
|
|
|
|
if (escape) {
|
|
if (write(fd, ((uint8_t *)buf) + start, end - start) < 0) {
|
|
goto error_io;
|
|
}
|
|
|
|
if (write(fd, escape, 2) < 0) {
|
|
goto error_io;
|
|
}
|
|
|
|
escape = NULL;
|
|
start = i + 1;
|
|
end = start;
|
|
}
|
|
}
|
|
|
|
if (end - start) {
|
|
if (write(fd, ((uint8_t *)buf) + start, end - start) < 0) {
|
|
goto error_io;
|
|
}
|
|
}
|
|
|
|
if (write_byte(fd, PATTY_KISS_FEND) < 0) {
|
|
goto error_io;
|
|
}
|
|
|
|
return len;
|
|
|
|
error_io:
|
|
return -1;
|
|
}
|