From bc865c798079968bf302b1309ee8c5afd7302f84 Mon Sep 17 00:00:00 2001 From: Matthias Wirth Date: Mon, 16 Sep 2024 16:52:11 +0200 Subject: [PATCH] couple of fixes to make ModeS beast work properly make modesbeast read nonblocking read returning zero not an error for serial clients --devel=debugSerial for some debugging for serial clients properly close serial client without unnecessary errors --- net_io.c | 59 +++++++++++++++++++++++++++++++++++++++++++---------- net_io.h | 1 + readsb.c | 3 +++ readsb.h | 1 + sdr_beast.c | 8 ++++++-- 5 files changed, 59 insertions(+), 13 deletions(-) diff --git a/net_io.c b/net_io.c index 30e4fd81..df105c58 100644 --- a/net_io.c +++ b/net_io.c @@ -318,6 +318,7 @@ static struct client *createSocketClient(struct net_service *service, int fd) { if ((c->fd == Modes.beast_fd) && (Modes.sdr_type == SDR_MODESBEAST || Modes.sdr_type == SDR_GNS)) { /* Message from a local connected Modes-S beast or GNS5894 are passed off the internet */ c->remote = 0; + c->serial = 1; } //fprintf(stderr, "c->receiverId: %016"PRIx64"\n", c->receiverId); @@ -1045,11 +1046,6 @@ void modesInitNet(void) { } serviceListen(Modes.beast_in_service, Modes.net_bind_address, Modes.net_input_beast_ports, Modes.net_epfd); - /* Beast input from local Modes-S Beast via USB */ - if (Modes.sdr_type == SDR_MODESBEAST || Modes.sdr_type == SDR_GNS) { - Modes.serial_client = createSocketClient(Modes.beast_in_service, Modes.beast_fd); - } - /* Planefinder input via network */ planefinder_in = serviceInit(&Modes.services_in, "Planefinder TCP input", NULL, no_heartbeat, no_heartbeat, READ_MODE_PLANEFINDER, NULL, decodePfMessage); serviceListen(planefinder_in, Modes.net_bind_address, Modes.net_input_planefinder_ports, Modes.net_epfd); @@ -1207,7 +1203,13 @@ static void modesCloseClient(struct client *c) { } epoll_ctl(Modes.net_epfd, EPOLL_CTL_DEL, c->fd, &c->epollEvent); - anetCloseSocket(c->fd); + if (c->serial) { + if (close(c->fd) < 0) { + fprintf(stderr, "Serial client close error: %s\n", strerror(errno)); + } + } else { + anetCloseSocket(c->fd); + } c->service->connections--; Modes.modesClientCount--; if (c->service->writer) { @@ -4438,7 +4440,15 @@ static int readClient(struct client *c, int64_t now) { nread = recv(c->fd, c->buf + c->buflen, left, 0); } else { // read instead of recv for modesbeast / gns-hulc .... + if (0 && Modes.debug_serial) { + fprintTimePrecise(stderr, mstime()); + fprintf(stderr, " serial read ... fd: %d maxbytes: %d\n", c->fd, left); + } nread = read(c->fd, c->buf + c->buflen, left); + if (nread > 0 && Modes.debug_serial) { + fprintTimePrecise(stderr, mstime()); + fprintf(stderr, " serial read return value: %d\n", nread); + } } int err = errno; @@ -4456,6 +4466,9 @@ static int readClient(struct client *c, int64_t now) { return 0; } // Other errors + if (c->serial) { + fprintf(stderr, "Serial client read error: %s\n", strerror(err)); + } if (Modes.debug_net) { fprintf(stderr, "%s: Socket Error: %s: %s port %s (fd %d, SendQ %d, RecvQ %d)\n", c->service->descr, strerror(err), c->host, c->port, @@ -4467,6 +4480,11 @@ static int readClient(struct client *c, int64_t now) { // End of file if (nread == 0) { + if (c->serial) { + // for serial this just means we're doing non-blocking reads and there are no bytes available + return 0; + } + if (c->con) { if (Modes.synthetic_now) { Modes.synthetic_now = 0; @@ -5392,8 +5410,12 @@ void modesNetPeriodicWork(void) { dump_beast_check(now); int64_t wait_ms; - if (Modes.serial_client) { - wait_ms = 20; + if (Modes.sdr_type == SDR_MODESBEAST || Modes.sdr_type == SDR_GNS) { + if (Modes.debug_serial) { + wait_ms = 1000; + } else { + wait_ms = 50; + } } else if (Modes.sdr_type != SDR_NONE) { // NO WAIT WHEN USING AN SDR !! IMPORTANT !! wait_ms = 0; @@ -5416,7 +5438,9 @@ void modesNetPeriodicWork(void) { Modes.services_in.event_progress = 0; Modes.services_out.event_progress = 0; - //fprintTimePrecise(stderr, now); fprintf(stderr, " event count %d wait_ms %d\n", Modes.net_event_count, (int) wait_ms); + if (Modes.debug_serial && Modes.net_event_count > 0) { + fprintTimePrecise(stderr, mstime()); fprintf(stderr, " event count %d wait_ms %d\n", Modes.net_event_count, (int) wait_ms); + } if (0 && Modes.net_event_count > 0) { fprintTimePrecise(stderr, now); fprintf(stderr, " event count %d wait_ms %d\n", Modes.net_event_count, (int) wait_ms); @@ -5456,10 +5480,23 @@ void modesNetPeriodicWork(void) { timespec_add_elapsed(&before, &after, &Modes.stats_current.background_cpu); } - if (Modes.serial_client) { + /* Beast input from local Modes-S Beast via USB */ + if (Modes.sdrInitialized && (Modes.sdr_type == SDR_MODESBEAST || Modes.sdr_type == SDR_GNS)) { + if (!Modes.serial_client) { + if (Modes.debug_serial) { + fprintTimePrecise(stderr, mstime()); + fprintf(stderr, " serial: creating socket client ... \n"); + } + Modes.serial_client = createSocketClient(Modes.beast_in_service, Modes.beast_fd); + if (Modes.debug_serial) { + fprintTimePrecise(stderr, mstime()); + fprintf(stderr, " serial: creating socket client ... done\n"); + } + } if (Modes.serial_client->service) { modesReadFromClient(Modes.serial_client, mb); - } else { + } + if (!Modes.serial_client->service) { fprintf(stderr, "Serial client closed unexpectedly, exiting!\n"); setExit(2); } diff --git a/net_io.h b/net_io.h index 344f1bad..7eb5e92f 100644 --- a/net_io.h +++ b/net_io.h @@ -100,6 +100,7 @@ struct client int fd; // File descriptor int8_t bufferToProcess; int8_t remote; + int8_t serial; int8_t bContinue; int8_t discard; int8_t processing; diff --git a/readsb.c b/readsb.c index 8292d919..4de6bafd 100644 --- a/readsb.c +++ b/readsb.c @@ -1972,6 +1972,9 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { if (strcasecmp(token[0], "debugGPS") == 0) { Modes.debug_gps = 1; } + if (strcasecmp(token[0], "debugSerial") == 0) { + Modes.debug_serial = 1; + } if (strcasecmp(token[0], "debugZstd") == 0) { Modes.debug_zstd = 1; } diff --git a/readsb.h b/readsb.h index 06064c11..533b59f1 100644 --- a/readsb.h +++ b/readsb.h @@ -639,6 +639,7 @@ struct _Modes int8_t mode_ac; // Enable decoding of SSR Modes A & C int8_t mode_ac_auto; // allow toggling of A/C by Beast commands int8_t debug_net; + int8_t debug_serial; int8_t debug_flush; int8_t debug_no_discard; int8_t debug_nextra; diff --git a/sdr_beast.c b/sdr_beast.c index d3e43056..2893f7d8 100644 --- a/sdr_beast.c +++ b/sdr_beast.c @@ -136,7 +136,9 @@ bool beastOpen(void) { struct termios tios; speed_t baud = B3000000; - Modes.beast_fd = open(Modes.beast_serial, O_RDWR | O_NOCTTY); + int flags = O_RDWR | O_NOCTTY; + //flags |= O_NONBLOCK; + Modes.beast_fd = open(Modes.beast_serial, flags); if (Modes.beast_fd < 0) { fprintf(stderr, "Failed to open serial device %s: %s\n", Modes.beast_serial, strerror(errno)); @@ -153,7 +155,8 @@ bool beastOpen(void) { tios.c_oflag = 0; tios.c_lflag = 0; tios.c_cflag = CS8 | CRTSCTS; - tios.c_cc[VMIN] = 11; + //tios.c_cc[VMIN] = 11; // read returns when a minimum of 11 characters are available + tios.c_cc[VMIN] = 0; // polling read with vtime 0 tios.c_cc[VTIME] = 0; if (Modes.sdr_type == SDR_GNS) { @@ -190,6 +193,7 @@ bool beastOpen(void) { if (Modes.sdr_type == SDR_MODESBEAST) { /* set options */ + beastSetOption('B'); /* set classic beast mode */ beastSetOption('C'); /* use binary format */ beastSetOption('H'); /* RTS enabled */