Skip to content

Commit

Permalink
gpsd 3.23 (API 12) compatibility and cleanups.
Browse files Browse the repository at this point in the history
  • Loading branch information
wb2osz committed Jan 2, 2022
1 parent 5dbe2ce commit 42314b7
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 72 deletions.
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@

- The BEACON configuration now recognizes the SOURCE= option. This replaces the AX.25 source address rather than using the MYCALL value for the channel. This is useful for sending more than 5 analog telemetry channels. Use two, or more, source addresses with up to 5 analog channels each.

- For more flexibility, the FX.25 transmit property can now be set individually by channel, rather than having a global setting for all channels. The -X on the command line applies only to channel 0. For other channels you need to add a new line to the configuration file.

> After: "CHANNEL 1" (or other channel)
>
> Add: "FX25TX 1" (or 16 or 32 or 64)

## Version 1.6 -- October 2020 ##
Expand Down
14 changes: 14 additions & 0 deletions src/ax25_link.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
* Establish connections and transfer data in the proper
* order with retries.
*
* Using the term "data link" is rather unfortunate because it causes
* confusion to someone familiar with the OSI networking model.
* This corresponds to the layer 4 transport, not layer 2 data link.
*
* Description:
*
* Typical sequence for establishing a connection
Expand Down Expand Up @@ -824,6 +828,11 @@ static ax25_dlsm_t *get_link_handle (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LE
// Create new data link state machine.

p = calloc (sizeof(ax25_dlsm_t), 1);
if (p == NULL) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("FATAL ERROR: Out of memory.\n");
exit (EXIT_FAILURE);
}
p->magic1 = MAGIC1;
p->start_time = dtime_now();
p->stream_id = next_stream_id++;
Expand Down Expand Up @@ -1493,6 +1502,11 @@ void dl_register_callsign (dlq_item_t *E)
}

r = calloc(sizeof(reg_callsign_t),1);
if (r == NULL) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("FATAL ERROR: Out of memory.\n");
exit (EXIT_FAILURE);
}
strlcpy (r->callsign, E->addrs[0], sizeof(r->callsign));
r->chan = E->chan;
r->client = E->client;
Expand Down
54 changes: 40 additions & 14 deletions src/decode_aprs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1377,9 +1377,14 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int

#define isT(c) ((c) == ' ' || (c) == '>' || (c) == ']' || (c) == '`' || (c) == '\'')

// Last updated Sept. 2016 for TH-D74A
// Last Updated Dec. 2021

// This does not change very often but I'm wondering if we could simply parse
// http://www.aprs.org/aprs12/mic-e-types.txt similar to how we use tocalls.txt.

if (isT(*pfirst)) {

// "legacy" formats.

if (*pfirst == ' ' ) { strlcpy (A->g_mfr, "Original MIC-E", sizeof(A->g_mfr)); pfirst++; }

Expand All @@ -1390,6 +1395,8 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
else if (*pfirst == ']' && *plast == '=') { strlcpy (A->g_mfr, "Kenwood TM-D710", sizeof(A->g_mfr)); pfirst++; plast--; }
else if (*pfirst == ']' ) { strlcpy (A->g_mfr, "Kenwood TM-D700", sizeof(A->g_mfr)); pfirst++; }

// ` should be used for message capable devices.

else if (*pfirst == '`' && *(plast-1) == '_' && *plast == ' ') { strlcpy (A->g_mfr, "Yaesu VX-8", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if (*pfirst == '`' && *(plast-1) == '_' && *plast == '"') { strlcpy (A->g_mfr, "Yaesu FTM-350", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if (*pfirst == '`' && *(plast-1) == '_' && *plast == '#') { strlcpy (A->g_mfr, "Yaesu VX-8G", sizeof(A->g_mfr)); pfirst++; plast-=2; }
Expand All @@ -1398,11 +1405,15 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
else if (*pfirst == '`' && *(plast-1) == '_' && *plast == ')') { strlcpy (A->g_mfr, "Yaesu FTM-100D", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if (*pfirst == '`' && *(plast-1) == '_' && *plast == '(') { strlcpy (A->g_mfr, "Yaesu FT2D", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if (*pfirst == '`' && *(plast-1) == '_' && *plast == '0') { strlcpy (A->g_mfr, "Yaesu FT3D", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if (*pfirst == '`' && *(plast-1) == '_' && *plast == '3') { strlcpy (A->g_mfr, "Yaesu FT5D", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if (*pfirst == '`' && *(plast-1) == '_' && *plast == '1') { strlcpy (A->g_mfr, "Yaesu FTM-300D", sizeof(A->g_mfr)); pfirst++; plast-=2; }

else if (*pfirst == '`' && *(plast-1) == ' ' && *plast == 'X') { strlcpy (A->g_mfr, "AP510", sizeof(A->g_mfr)); pfirst++; plast-=2; }

else if (*pfirst == '`' && *(plast-1) == '(' && *plast == '5') { strlcpy (A->g_mfr, "Anytone D578UV", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if (*pfirst == '`' ) { strlcpy (A->g_mfr, "Generic Mic-Emsg", sizeof(A->g_mfr)); pfirst++; }

else if (*pfirst == '`' ) { strlcpy (A->g_mfr, "Mic-Emsg", sizeof(A->g_mfr)); pfirst++; }
// ' should be used for trackers (not message capable).

else if (*pfirst == '\'' && *(plast-1) == '(' && *plast == '8') { strlcpy (A->g_mfr, "Anytone D878UV", sizeof(A->g_mfr)); pfirst++; plast-=2; }

Expand All @@ -1412,13 +1423,13 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
else if (*pfirst == '\'' && *(plast-1) == ':' && *plast == '4') { strlcpy (A->g_mfr, "SCS GmbH & Co. P4dragon DR-7400 modems", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if (*pfirst == '\'' && *(plast-1) == ':' && *plast == '8') { strlcpy (A->g_mfr, "SCS GmbH & Co. P4dragon DR-7800 modems", sizeof(A->g_mfr)); pfirst++; plast-=2; }

else if (*pfirst == '\'' ) { strlcpy (A->g_mfr, "McTrackr", sizeof(A->g_mfr)); pfirst++; }
else if (*pfirst == '\'' ) { strlcpy (A->g_mfr, "Generic McTrackr", sizeof(A->g_mfr)); pfirst++; }

else if ( *(plast-1) == '\\' ) { strlcpy (A->g_mfr, "Hamhud ?", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if ( *(plast-1) == '/' ) { strlcpy (A->g_mfr, "Argent ?", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if ( *(plast-1) == '^' ) { strlcpy (A->g_mfr, "HinzTec anyfrog", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if ( *(plast-1) == '*' ) { strlcpy (A->g_mfr, "APOZxx www.KissOZ.dk Tracker. OZ1EKD and OZ7HVO", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if ( *(plast-1) == '~' ) { strlcpy (A->g_mfr, "OTHER", sizeof(A->g_mfr)); pfirst++; plast-=2; }
else if ( *(plast-1) == '~' ) { strlcpy (A->g_mfr, "Unknown OTHER", sizeof(A->g_mfr)); pfirst++; plast-=2; }
}

/*
Expand Down Expand Up @@ -3486,6 +3497,8 @@ time_t get_timestamp (decode_aprs_t *A, char *p)
time_t ts;

ts = time(NULL);
// FIXME: use gmtime_r instead.
// Besides not being thread safe, gmtime could possibly return null.
ptm = gmtime(&ts);

pdhm = (void *)p;
Expand Down Expand Up @@ -4211,9 +4224,7 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen)
dw_printf("%s:%d: %s\n", __FILE__, __LINE__, emsg);
}

// TODO: Would like to restrict to even length something like this: ([!-{][!-{]){2,7}

e = regcomp (&base91_tel_re, "\\|([!-{]{4,14})\\|", REG_EXTENDED);
e = regcomp (&base91_tel_re, "\\|(([!-{][!-{]){2,7})\\|", REG_EXTENDED);
if (e) {
regerror (e, &base91_tel_re, emsg, sizeof(emsg));
dw_printf("%s:%d: %s\n", __FILE__, __LINE__, emsg);
Expand Down Expand Up @@ -4411,20 +4422,20 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen)

/*
* Telemetry data, in base 91 compressed format appears as 2 to 7 pairs
* of base 91 digits, surrounded by | at start and end.
* of base 91 digits, ! thru {, surrounded by | at start and end.
*/


if (regexec (&base91_tel_re, A->g_comment, MAXMATCH, match, 0) == 0)
{

char tdata[30]; /* Should be 4 to 14 characters. */
char tdata[30]; /* Should be even number of 4 to 14 characters. */

//dw_printf("compressed telemetry start=%d, end=%d\n", (int)(match[0].rm_so), (int)(match[0].rm_eo));
//dw_printf("compressed telemetry start=%d, end=%d\n", (int)(match[0].rm_so), (int)(match[0].rm_eo));

substr_se (tdata, A->g_comment, match[1].rm_so, match[1].rm_eo);

//dw_printf("compressed telemetry data = \"%s\"\n", tdata);
//dw_printf("compressed telemetry data = \"%s\"\n", tdata);

telemetry_data_base91 (A->g_src, tdata, A->g_telemetry, sizeof(A->g_telemetry));

Expand All @@ -4442,6 +4453,8 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen)
*
* It surprised me to see this in a MIC-E message.
* MIC-E has resolution of .01 minute so it would make sense to have it as an option.
* We also find an example in http://www.aprs.org/aprs12/mic-e-examples.txt
* 'abc123R/'123}FFF.FFFMHztext.../A=123456...!DAO! Mv
*/

if (regexec (&dao_re, A->g_comment, MAXMATCH, match, 0) == 0)
Expand All @@ -4451,7 +4464,7 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen)
int a = A->g_comment[match[0].rm_so+2];
int o = A->g_comment[match[0].rm_so+3];

//dw_printf("start=%d, end=%d\n", (int)(match[0].rm_so), (int)(match[0].rm_eo));
dw_printf("DAO start=%d, end=%d\n", (int)(match[0].rm_so), (int)(match[0].rm_eo));


/*
Expand Down Expand Up @@ -4503,7 +4516,7 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen)
*/

/*
* Here is an interesting case.
* Here are a couple situations where it is seen.
*
* W8SAT-1>T2UV0P:`qC<0x1f>l!Xu\'"69}WMNI EDS Response Unit #1|+/%0'n|!w:X!|3
*
Expand All @@ -4520,13 +4533,26 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen)
* Comment earlier points out that MIC-E format has resolution of 0.01 minute,
* same as non-compressed format, so the DAO does work out, after thinking
* about it for a while.
* We also find a MIC-E example with !DAO! here: http://www.aprs.org/aprs12/mic-e-examples.txt
*
* Another one:
*
* KS4FUN-12>3X0PRU,W6CX-3,BKELEY,WIDE2*:`2^=l!<0x1c>+/'"48}MT-RTG|%B%p'a|!wqR!|3
*
* MIC-E, Red Cross, Special
* N 38 00.2588, W 122 06.3354
* 0 MPH, course 100, alt 108 ft
* MT-RTG comment
* |%B%p'a| Seq=397, A1=443, A2=610
* !wqR! DAO
* |3 Byonics TinyTrack3
*
*/

/*
* The spec appears to be wrong. It says '}' is the maximum value when it should be '{'.
*/


if (isdigit91(a)) {
A->g_lat += (a - B91_MIN) * 1.1 / 600000.0 * sign(A->g_lat);
}
Expand Down
12 changes: 10 additions & 2 deletions src/dwgpsd.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//
// This file is part of Dire Wolf, an amateur radio packet TNC.
//
// Copyright (C) 2013, 2014, 2015, 2020 John Langner, WB2OSZ
// Copyright (C) 2013, 2014, 2015, 2020, 2022 John Langner, WB2OSZ
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -60,7 +60,11 @@
// An incompatibility was introduced with version 7
// and again with 9 and again with 10.

#if GPSD_API_MAJOR_VERSION < 5 || GPSD_API_MAJOR_VERSION > 11
// release lib version API Raspberry Pi OS
// 3.22 28 11 bullseye
// 3.23 29 12

#if GPSD_API_MAJOR_VERSION < 5 || GPSD_API_MAJOR_VERSION > 12
#error libgps API version might be incompatible.
#endif

Expand Down Expand Up @@ -364,6 +368,10 @@ static void * read_gpsd_thread (void *arg)
default:
case MODE_NOT_SEEN:
case MODE_NO_FIX:
if (info.fix <= DWFIX_NOT_SEEN) {
text_color_set(DW_COLOR_INFO);
dw_printf ("GPSD: No location fix.\n");
}
if (info.fix >= DWFIX_2D) {
text_color_set(DW_COLOR_INFO);
dw_printf ("GPSD: Lost location fix.\n");
Expand Down
Loading

0 comments on commit 42314b7

Please sign in to comment.