Skip to content

Commit

Permalink
couple of fixes to make ModeS beast work properly
Browse files Browse the repository at this point in the history
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
  • Loading branch information
wiedehopf committed Sep 16, 2024
1 parent 6035235 commit 66857d3
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 13 deletions.
55 changes: 44 additions & 11 deletions net_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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 > -1 && Modes.debug_serial) {
fprintTimePrecise(stderr, mstime());
fprintf(stderr, " serial read return value: %d\n", nread);
}
}
int err = errno;

Expand All @@ -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,
Expand All @@ -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;
Expand Down Expand Up @@ -5392,8 +5410,8 @@ 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) {
wait_ms = 100;
} else if (Modes.sdr_type != SDR_NONE) {
// NO WAIT WHEN USING AN SDR !! IMPORTANT !!
wait_ms = 0;
Expand All @@ -5416,7 +5434,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);
Expand Down Expand Up @@ -5456,10 +5476,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);
}
Expand Down
1 change: 1 addition & 0 deletions net_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions readsb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
1 change: 1 addition & 0 deletions readsb.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 6 additions & 2 deletions sdr_beast.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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) {
Expand Down Expand Up @@ -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 */

Expand Down

0 comments on commit 66857d3

Please sign in to comment.