mirror of https://github.com/wb2osz/direwolf.git
Use tocalls.yaml rather than tocalls.txt which is no longer maintained.
This commit is contained in:
parent
d679e06846
commit
46f31d4453
|
@ -2,6 +2,12 @@
|
||||||
# Revision History #
|
# Revision History #
|
||||||
|
|
||||||
|
|
||||||
|
## Version 1.8 -- Development Version
|
||||||
|
|
||||||
|
### New Features: ###
|
||||||
|
|
||||||
|
- [http://www.aprs.org/aprs11/tocalls.txt](http://www.aprs.org/aprs11/tocalls.txt) has been abandoned since the end of 2021. [https://github.com/aprsorg/aprs-deviceid](https://github.com/aprsorg/aprs-deviceid) is now considered to be the authoritative source of truth for the vendor/model encoding.
|
||||||
|
|
||||||
## Version 1.7 -- October 2023 ##
|
## Version 1.7 -- October 2023 ##
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#
|
#
|
||||||
# The destination field is often used to identify the manufacturer/model.
|
# The destination field is often used to identify the manufacturer/model.
|
||||||
# These are not hardcoded into Dire Wolf. Instead they are read from
|
# These are not hardcoded into Dire Wolf. Instead they are read from
|
||||||
# a file called tocalls.txt at application start up time.
|
# a file called tocalls.yaml at application start up time.
|
||||||
#
|
#
|
||||||
# The original permanent symbols are built in but the "new" symbols,
|
# The original permanent symbols are built in but the "new" symbols,
|
||||||
# using overlays, are often updated. These are also read from files.
|
# using overlays, are often updated. These are also read from files.
|
||||||
|
@ -25,17 +25,17 @@
|
||||||
|
|
||||||
include(ExternalProject)
|
include(ExternalProject)
|
||||||
|
|
||||||
set(TOCALLS_TXT "tocalls.txt")
|
set(TOCALLS_YAML "tocalls.yaml")
|
||||||
set(SYMBOLS-NEW_TXT "symbols-new.txt")
|
set(SYMBOLS-NEW_TXT "symbols-new.txt")
|
||||||
set(SYMBOLSX_TXT "symbolsX.txt")
|
set(SYMBOLSX_TXT "symbolsX.txt")
|
||||||
set(CUSTOM_BINARY_DATA_DIR "${CMAKE_BINARY_DIR}/data")
|
set(CUSTOM_BINARY_DATA_DIR "${CMAKE_BINARY_DIR}/data")
|
||||||
|
|
||||||
# we can also move to a separate cmake file and use file(download)
|
# we can also move to a separate cmake file and use file(download)
|
||||||
# see conf/install_conf.cmake as example
|
# see conf/install_conf.cmake as example
|
||||||
file(COPY "${CUSTOM_DATA_DIR}/${TOCALLS_TXT}" DESTINATION "${CUSTOM_BINARY_DATA_DIR}")
|
file(COPY "${CUSTOM_DATA_DIR}/${TOCALLS_YAML}" DESTINATION "${CUSTOM_BINARY_DATA_DIR}")
|
||||||
file(COPY "${CUSTOM_DATA_DIR}/${SYMBOLS-NEW_TXT}" DESTINATION "${CUSTOM_BINARY_DATA_DIR}")
|
file(COPY "${CUSTOM_DATA_DIR}/${SYMBOLS-NEW_TXT}" DESTINATION "${CUSTOM_BINARY_DATA_DIR}")
|
||||||
file(COPY "${CUSTOM_DATA_DIR}/${SYMBOLSX_TXT}" DESTINATION "${CUSTOM_BINARY_DATA_DIR}")
|
file(COPY "${CUSTOM_DATA_DIR}/${SYMBOLSX_TXT}" DESTINATION "${CUSTOM_BINARY_DATA_DIR}")
|
||||||
|
|
||||||
install(FILES "${CUSTOM_BINARY_DATA_DIR}/${TOCALLS_TXT}" DESTINATION ${INSTALL_DATA_DIR})
|
install(FILES "${CUSTOM_BINARY_DATA_DIR}/${TOCALLS_YAML}" DESTINATION ${INSTALL_DATA_DIR})
|
||||||
install(FILES "${CUSTOM_BINARY_DATA_DIR}/${SYMBOLS-NEW_TXT}" DESTINATION ${INSTALL_DATA_DIR})
|
install(FILES "${CUSTOM_BINARY_DATA_DIR}/${SYMBOLS-NEW_TXT}" DESTINATION ${INSTALL_DATA_DIR})
|
||||||
install(FILES "${CUSTOM_BINARY_DATA_DIR}/${SYMBOLSX_TXT}" DESTINATION ${INSTALL_DATA_DIR})
|
install(FILES "${CUSTOM_BINARY_DATA_DIR}/${SYMBOLSX_TXT}" DESTINATION ${INSTALL_DATA_DIR})
|
||||||
|
|
326
data/tocalls.txt
326
data/tocalls.txt
|
@ -1,326 +0,0 @@
|
||||||
<title>
|
|
||||||
APRS TO-CALL VERSION NUMBERS 14 Dec 2021
|
|
||||||
---------------------------------------------------------------------
|
|
||||||
WB4APR
|
|
||||||
</title>
|
|
||||||
<version_notes>
|
|
||||||
07 Jun 23 Added APK005 for Kenwood TH-D75
|
|
||||||
14 Dec 21 Added APATAR ATA-R APRS Digipeater by TA7W/OH2UDS and TA6AEU
|
|
||||||
26 Sep 21 Added APRRDZ EPS32 https://github.com/dl9rdz/rdz_ttgo_sonde
|
|
||||||
18 Sep 21 Added APCSS for AMSAT Cubesat Simulator https://cubesatsim.org
|
|
||||||
16 Sep 21 Added APY05D for Yaesu FT5D series
|
|
||||||
04 Sep 21 APLOxx LoRa KISS TNC/Tracker https://github.com/SQ9MDD/TTGO-T-Beam-LoRa-APRS
|
|
||||||
24 Aug 21 Added APLSxx SARIMESH http://www.sarimesh.net
|
|
||||||
22 Aug 21 Added APE2Ax for VA3NNW's Email-2-APRS ap
|
|
||||||
30 Jun 21 Added APCNxx for carNET by DG5OAW
|
|
||||||
14 Jun 21 Added APN2xx for NOSaprs JNOS 2.0 - VE4KLM
|
|
||||||
24 Apr 21 Added APMPAD for DF1JSL's WXBot clone and extension
|
|
||||||
20 Apr 21 Added APLCxx for APRScube by DL3DCW
|
|
||||||
19 Apr 21 Added APVMxx for DRCC-DVM Voice (Digital Radio China Club)
|
|
||||||
13 Apr 21 Added APIxxx for all Dstar ICOMS (APRS via DPRS)
|
|
||||||
23 MAr 20 Added APW9xx For 9A9Y Weather Tracker
|
|
||||||
16 Feb 21 Added API970 for I com 9700
|
|
||||||
|
|
||||||
2020 Added APHBLx,APIZCI,APLGxx,APLTxx,APNVxx,APY300,APESPG,APESPW
|
|
||||||
APGDTx,APOSWx,APOSBx,APBT62,APCLUB,APMQxx
|
|
||||||
2019 Added APTPNx,APJ8xx,APBSDx,APNKMX,APAT51,APMGxx,APTCMA,
|
|
||||||
APATxx,APQTHx,APLIGx
|
|
||||||
2018 added APRARX,APELKx,APGBLN,APBKxx,APERSx,APTCHE
|
|
||||||
2017 Added APHWxx,APDVxx,APPICO,APBMxx,APP6xx,APTAxx,APOCSG,APCSMS,
|
|
||||||
APPMxx,APOFF,APDTMF,APRSON,APDIGI,APSAT,APTBxx,APIExx,
|
|
||||||
APSFxx
|
|
||||||
2016 added APYSxx,APINxx,APNICx,APTKPT,APK004,APFPRS,APCDS0,APDNOx
|
|
||||||
2015 Added APSTPO,APAND1,APDRxx,APZ247,APHTxx,APMTxx,APZMAJ
|
|
||||||
APB2MF,APR2MF,APAVT5
|
|
||||||
|
|
||||||
</version_notes>
|
|
||||||
<description>
|
|
||||||
|
|
||||||
In APRS, the AX.25 Destination address is not used for packet
|
|
||||||
routing as is normally done in AX.25. So APRS uses it for two
|
|
||||||
things. The initial APxxxx is used as a group identifier to make
|
|
||||||
APRS packets instanantly recognizable on shared channels. Most
|
|
||||||
applicaitons ignore all non APRS packets. The remaining 4 xxxx
|
|
||||||
bytes of the field are available to indicate the software version
|
|
||||||
number or application. The following applications have requested
|
|
||||||
a TOCALL number series:
|
|
||||||
|
|
||||||
Authors with similar alphabetic requirements are encouraged to share
|
|
||||||
their address space with other software. Work out agreements amongst
|
|
||||||
yourselves and keep me informed.
|
|
||||||
|
|
||||||
</description>
|
|
||||||
<tocalls>
|
|
||||||
|
|
||||||
APn 3rd digit is a number
|
|
||||||
AP1WWX TAPR T-238+ WX station
|
|
||||||
AP1MAJ Martyn M1MAJ DeLorme inReach Tracker
|
|
||||||
AP4Rxy APRS4R software interface
|
|
||||||
APnnnD Painter Engineering uSmartDigi D-Gate DSTAR Gateway
|
|
||||||
APnnnU Painter Engineering uSmartDigi Digipeater
|
|
||||||
APA APAFxx AFilter.
|
|
||||||
APAGxx AGATE
|
|
||||||
APAGWx SV2AGW's AGWtracker
|
|
||||||
APALxx Alinco DR-620/635 internal TNC digis. "Hachi" ,JF1AJE
|
|
||||||
APAXxx AFilterX.
|
|
||||||
APAHxx AHub
|
|
||||||
APAND1 APRSdroid (pre-release) http://aprsdroid.org/
|
|
||||||
APAMxx Altus Metrum GPS trackers
|
|
||||||
APATAR ATA-R APRS Digipeater by TA7W/OH2UDS and TA6AEU
|
|
||||||
APAT8x for Anytone. 81 for 878 HT
|
|
||||||
APAT51 for Anytone AT-D578UV APRS mobile radio
|
|
||||||
APAVT5 SainSonic AP510 which is a 1watt tracker
|
|
||||||
APAWxx AGWPE
|
|
||||||
APB APBxxx Beacons or Rabbit TCPIP micros?
|
|
||||||
APB2MF DL2MF - MF2APRS Radiosonde for balloons
|
|
||||||
APBLxx BigRedBee BeeLine
|
|
||||||
APBLO MOdel Rocketry K7RKT
|
|
||||||
APBKxx PY5BK Bravo Tracker in Brazil
|
|
||||||
APBPQx John G8BPQ Digipeater/IGate
|
|
||||||
APBMxx BrandMeister DMR Server for R3ABM
|
|
||||||
APBSDx HamBSD https://hambsd.org/
|
|
||||||
APBT62 BTech DMR 6x2
|
|
||||||
APC APCxxx Cellular applications
|
|
||||||
APCBBx VE7UDP Blackberry Applications
|
|
||||||
APCDS0 Leon Lessing ZS6LMG's cell tracker
|
|
||||||
APCLEY EYTraker GPRS/GSM tracker by ZS6EY
|
|
||||||
APCLEZ Telit EZ10 GSM application ZS6CEY
|
|
||||||
APCLUB Brazil APRS network
|
|
||||||
APCLWX EYWeather GPRS/GSM WX station by ZS6EY
|
|
||||||
APCNxx for carNET by DG5OAW
|
|
||||||
APCSMS for Cosmos (used for sending commands @USNA)
|
|
||||||
APCSS for AMSAT cubesats https://cubesatsim.org
|
|
||||||
APCWP8 John GM7HHB, WinphoneAPRS
|
|
||||||
APCYxx Cybiko applications
|
|
||||||
APD APD4xx UP4DAR platform
|
|
||||||
APDDxx DV-RPTR Modem and Control Center Software
|
|
||||||
APDFxx Automatic DF units
|
|
||||||
APDGxx D-Star Gateways by G4KLX ircDDB
|
|
||||||
APDHxx WinDV (DUTCH*Star DV Node for Windows)
|
|
||||||
APDInn DIXPRS - Bela, HA5DI
|
|
||||||
APDIGI Used by PSAT2 to indicate the digi is ON
|
|
||||||
APDIGI digi ON for PSAT2 and QIKCOM-2
|
|
||||||
APDKxx KI4LKF g2_ircddb Dstar gateway software
|
|
||||||
APDNOx APRSduino by DO3SWW
|
|
||||||
APDOxx ON8JL Standalone DStar Node
|
|
||||||
APDPRS D-Star originated posits
|
|
||||||
APDRxx APRSdroid Android App http://aprsdroid.org/
|
|
||||||
APDSXX SP9UOB for dsDigi and ds-tracker
|
|
||||||
APDTxx APRStouch Tone (DTMF)
|
|
||||||
APDTMF digi off mode on QIKCOM2 and DTMF ON
|
|
||||||
APDUxx U2APRS by JA7UDE
|
|
||||||
APDVxx OE6PLD's SSTV with APRS status exchange
|
|
||||||
APDWxx DireWolf, WB2OSZ
|
|
||||||
APE APExxx Telemetry devices
|
|
||||||
APE2Ax VA3NNW's Email-2-APRS ap
|
|
||||||
APECAN Pecan Pico APRS Balloon Tracker
|
|
||||||
APELKx WB8ELK balloons
|
|
||||||
APERXQ Experimental tracker by PE1RXQ
|
|
||||||
APERSx Runner tracking by Jason,KG7YKZ
|
|
||||||
APESPG ESP SmartBeacon APRS-IS Client
|
|
||||||
APESPW ESP Weather Station APRS-IS Client
|
|
||||||
APF APFxxx Firenet
|
|
||||||
APFGxx Flood Gage (KP4DJT)
|
|
||||||
APFIxx for APRS.FI OH7LZB, Hessu
|
|
||||||
APFPRS for FreeDV by Jeroen PE1RXQ
|
|
||||||
APG APGxxx Gates, etc
|
|
||||||
APGOxx for AA3NJ PDA application
|
|
||||||
APGBLN for NW5W's GoBalloon
|
|
||||||
APGDTx for VK4FAST's Graphic Data Terminal
|
|
||||||
APH APHKxx for LA1BR tracker/digipeater
|
|
||||||
APHAXn SM2APRS by PY2UEP
|
|
||||||
APHBLx for DMR Gateway by Eric - KF7EEL
|
|
||||||
APHTxx HMTracker by IU0AAC
|
|
||||||
APHWxx for use in "HamWAN
|
|
||||||
API API282 for ICOM IC-2820
|
|
||||||
API31 for ICOM ID-31
|
|
||||||
API410 for ICOM ID-4100
|
|
||||||
API51 for ICOM ID-51
|
|
||||||
API510 for ICOM ID-5100
|
|
||||||
API710 for ICOM IC-7100
|
|
||||||
API80 for ICOM IC-80
|
|
||||||
API880 for ICOM ID-880
|
|
||||||
API910 for ICOM IC-9100
|
|
||||||
API92 for ICOM IC-92
|
|
||||||
API970 for ICOM 9700
|
|
||||||
APICQx for ICQ
|
|
||||||
APICxx HA9MCQ's Pic IGate
|
|
||||||
APIExx W7KMV's PiAPRS system
|
|
||||||
APINxx PinPoint by AB0WV
|
|
||||||
APIZCI hymTR IZCI Tracker by TA7W/OH2UDS and TA6AEU
|
|
||||||
APJ APJ8xx Jordan / KN4CRD JS8Call application
|
|
||||||
APJAxx JavAPRS
|
|
||||||
APJExx JeAPRS
|
|
||||||
APJIxx jAPRSIgate
|
|
||||||
APJSxx javAPRSSrvr
|
|
||||||
APJYnn KA2DDO Yet another APRS system
|
|
||||||
APK APK0xx Kenwood TH-D7's
|
|
||||||
APK003 Kenwood TH-D72
|
|
||||||
APK004 Kenwood TH-D74
|
|
||||||
APK005 Kenwood TH-D75
|
|
||||||
APK1xx Kenwood D700's
|
|
||||||
APK102 Kenwood D710
|
|
||||||
APKRAM KRAMstuff.com - Mark. G7LEU
|
|
||||||
APL APLCxx APRScube by DL3DCW
|
|
||||||
APLGxx LoRa Gateway/Digipeater OE5BPA
|
|
||||||
APLIGx LightAPRS - TA2MUN and TA9OHC
|
|
||||||
APLOxx LoRa KISS TNC/Tracker
|
|
||||||
APLQRU Charlie - QRU Server
|
|
||||||
APLMxx WA0TQG transceiver controller
|
|
||||||
APLSxx SARIMESH ( http://www.sarimesh.net )
|
|
||||||
APLTxx LoRa Tracker - OE5BPA
|
|
||||||
APM APMxxx MacAPRS,
|
|
||||||
APMGxx PiCrumbs and MiniGate - Alex, AB0TJ
|
|
||||||
APMIxx SQ3PLX http://microsat.com.pl/
|
|
||||||
APMPAD DF1JSL's WXBot clone and extension
|
|
||||||
APMQxx Ham Radio of Things WB2OSZ
|
|
||||||
APMTxx LZ1PPL for tracker
|
|
||||||
APN APNxxx Network nodes, digis, etc
|
|
||||||
APN2xx NOSaprs for JNOS 2.0 - VE4KLM
|
|
||||||
APN3xx Kantronics KPC-3 rom versions
|
|
||||||
APN9xx Kantronics KPC-9612 Roms
|
|
||||||
APNAxx WB6ZSU's APRServe
|
|
||||||
APNDxx DIGI_NED
|
|
||||||
APNICx SQ5EKU http://sq5eku.blogspot.com/
|
|
||||||
APNK01 Kenwood D700 (APK101) type
|
|
||||||
APNK80 KAM version 8.0
|
|
||||||
APNKMP KAM+
|
|
||||||
APNKMX KAM-XL
|
|
||||||
APNMxx MJF TNC roms
|
|
||||||
APNPxx Paccom TNC roms
|
|
||||||
APNTxx SV2AGW's TNT tnc as a digi
|
|
||||||
APNUxx UIdigi
|
|
||||||
APNVxx SQ8L's VP digi and Nodes
|
|
||||||
APNXxx TNC-X (K6DBG)
|
|
||||||
APNWxx SQ3FYK.com WX/Digi and SQ3PLX http://microsat.com.pl/
|
|
||||||
APO APRSpoint
|
|
||||||
APOFF Used by PSAT and PSAT2 to indicate the digi is OFF
|
|
||||||
APOLUx for OSCAR satellites for AMSAT-LU by LU9DO
|
|
||||||
APOAxx OpenAPRS - Greg Carter
|
|
||||||
APOCSG For N0AGI's APRS to POCSAG project
|
|
||||||
APOD1w Open Track with 1 wire WX
|
|
||||||
APOSBx openSPOT3 by HA2NON at sharkrf.com
|
|
||||||
APOSWx openSPOT2
|
|
||||||
APOTxx Open Track
|
|
||||||
APOU2k Open Track for Ultimeter
|
|
||||||
APOZxx www.KissOZ.dk Tracker. OZ1EKD and OZ7HVO
|
|
||||||
APP APP6xx for APRSlib
|
|
||||||
APPICx DB1NTO' PicoAPRS
|
|
||||||
APPMxx DL1MX's RTL-SDR pytohon Igate
|
|
||||||
APPTxx KetaiTracker by JF6LZE, Takeki (msg capable)
|
|
||||||
APQ APQxxx Earthquake data
|
|
||||||
APQTHx W8WJB's QTH.app
|
|
||||||
APR APR8xx APRSdos versions 800+
|
|
||||||
APR2MF DL2MF - MF2APRS Radiosonde WX reporting
|
|
||||||
APRARX VK5QI's radiosonde tracking
|
|
||||||
APRDxx APRSdata, APRSdr
|
|
||||||
APRGxx aprsg igate software, OH2GVE
|
|
||||||
APRHH2 HamHud 2
|
|
||||||
APRKxx APRStk
|
|
||||||
APRNOW W5GGW ipad application
|
|
||||||
APRRTx RPC electronics
|
|
||||||
APRS Generic, (obsolete. Digis should use APNxxx instead)
|
|
||||||
APRSON Used by PSAT to indicate the DIGI is ON
|
|
||||||
APRXxx >40 APRSmax
|
|
||||||
APRXxx <39 for OH2MQK's igate
|
|
||||||
APRTLM used in MIM's and Mic-lites, etc
|
|
||||||
APRtfc APRStraffic
|
|
||||||
APRSTx APRStt (Touch tone)
|
|
||||||
APS APSxxx APRS+SA, etc
|
|
||||||
APSARx ZL4FOX's SARTRACK
|
|
||||||
APSAT digi ON for QIKCOM-1
|
|
||||||
APSCxx aprsc APRS-IS core server (OH7LZB, OH2MQK)
|
|
||||||
APSFxx F5OPV embedded devices - was APZ40
|
|
||||||
APSK63 APRS Messenger -over-PSK63
|
|
||||||
APSK25 APRS Messenger GMSK-250
|
|
||||||
APSMSx Paul Dufresne's SMSGTE - SMS Gateway
|
|
||||||
APSTMx for W7QO's Balloon trackers
|
|
||||||
APSTPO for N0AGI Satellite Tracking and Operations
|
|
||||||
APT APT2xx Tiny Track II
|
|
||||||
APT3xx Tiny Track III
|
|
||||||
APTAxx K4ATM's tiny track
|
|
||||||
APTBxx TinyAPRS by BG5HHP Was APTAxx till Sep 2017
|
|
||||||
APTCHE PU3IKE in Brazil TcheTracker/Tcheduino
|
|
||||||
APTCMA CAPI tracker - PU1CMA Brazil
|
|
||||||
APTIGR TigerTrack
|
|
||||||
APTKPT TrackPoint N0LP
|
|
||||||
APTPNx TARPN Packet Node Tracker by KN4ORB http://tarpn.net/
|
|
||||||
APTTxx Tiny Track
|
|
||||||
APTWxx Byons WXTrac
|
|
||||||
APTVxx for ATV/APRN and SSTV applications
|
|
||||||
APU APU1xx UIview 16 bit applications
|
|
||||||
APU2xx UIview 32 bit apps
|
|
||||||
APU3xx UIview terminal program
|
|
||||||
APUDRx NW Digital Radio's UDR (APRS/Dstar)
|
|
||||||
APV APVxxx Voice over Internet applications
|
|
||||||
APVMxx DRCC-DVM Digital Voice (Digital Radio China Club)
|
|
||||||
APVRxx for IRLP
|
|
||||||
APVLxx for I-LINK
|
|
||||||
APVExx for ECHO link
|
|
||||||
APW APWxxx WinAPRS, etc
|
|
||||||
APW9xx 9A9Y Weather Tracker
|
|
||||||
APWAxx APRSISCE Android version
|
|
||||||
APWSxx DF4IAN's WS2300 WX station
|
|
||||||
APWMxx APRSISCE KJ4ERJ
|
|
||||||
APWWxx APRSISCE win32 version
|
|
||||||
APX APXnnn Xastir
|
|
||||||
APXRnn Xrouter
|
|
||||||
APY APYxxx Yaesu Radios
|
|
||||||
APY008 Yaesu VX-8 series
|
|
||||||
APY01D Yaesu FT1D series
|
|
||||||
APY02D Yaesu FT2D series
|
|
||||||
APY03D Yaesu FT3D series
|
|
||||||
APY05D Yaesu FT5D series
|
|
||||||
APY100 Yaesu FTM-100D series
|
|
||||||
APY300 Yaesu FTM-300D series
|
|
||||||
APY350 Yaesu FTM-350 series
|
|
||||||
APY400 Yaesu FTM-400D series
|
|
||||||
APZ APZxxx Experimental
|
|
||||||
APZ200 old versions of JNOS
|
|
||||||
APZ247 for UPRS NR0Q
|
|
||||||
APZ0xx Xastir (old versions. See APX)
|
|
||||||
APZMAJ Martyn M1MAJ DeLorme inReach Tracker
|
|
||||||
APZMDM github/codec2_talkie - product code not registered
|
|
||||||
APZMDR for HaMDR trackers - hessu * hes.iki.fi]
|
|
||||||
APZPAD Smart Palm
|
|
||||||
APZTKP TrackPoint, Nick N0LP (Balloon tracking)(depricated)
|
|
||||||
APZWIT MAP27 radio (Mountain Rescue) EI7IG
|
|
||||||
APZWKR GM1WKR NetSked application
|
|
||||||
</tocalls>
|
|
||||||
<notes>
|
|
||||||
|
|
||||||
</notes>
|
|
||||||
<altnets>
|
|
||||||
|
|
||||||
REGISTERED TOCALL ALTNETS:
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
ALTNETS are uses of the AX-25 tocall to distinguish specialized
|
|
||||||
traffic that may be flowing on the APRS-IS, but that are not intended
|
|
||||||
to be part of normal APRS distribution to all normal APRS software
|
|
||||||
operating in normal (default) modes. Proper APRS software that
|
|
||||||
honors this design are supposed to IGNORE all ALTNETS unless the
|
|
||||||
particular operator has selected an ALTNET to monitor for.
|
|
||||||
|
|
||||||
An example is when testing; an author may want to transmit objects
|
|
||||||
all over his map for on-air testing, but does not want these to
|
|
||||||
clutter everyone's maps or databases. He could use the ALTNET of
|
|
||||||
"TEST" and client APRS software that respects the ALTNET concept
|
|
||||||
should ignore these packets.
|
|
||||||
|
|
||||||
An ALTNET is defined to be ANY AX.25 TOCALL that is NOT one of the
|
|
||||||
normal APRS TOCALL's. The normal TOCALL's that APRS is supposed to
|
|
||||||
process are: ALL, BEACON, CQ, QST, GPSxxx and of course APxxxx.
|
|
||||||
|
|
||||||
The following is a list of ALTNETS that may be of interest to other
|
|
||||||
users. This list is by no means complete, since ANY combination of
|
|
||||||
characters other than APxxxx are considered an ALTNET. But this list
|
|
||||||
can give consisntecy to ALTNETS that may be using the global APRS-IS
|
|
||||||
and need some special recognition. Here are some ideas:
|
|
||||||
</altnets>
|
|
||||||
<altnet_list>
|
|
||||||
|
|
||||||
SATERN - Salvation Army Altnet
|
|
||||||
AFMARS - Airforce Mars
|
|
||||||
AMARS - Army Mars
|
|
||||||
</altnet_list>
|
|
File diff suppressed because it is too large
Load Diff
|
@ -33,6 +33,7 @@ list(APPEND direwolf_SOURCES
|
||||||
beacon.c
|
beacon.c
|
||||||
config.c
|
config.c
|
||||||
decode_aprs.c
|
decode_aprs.c
|
||||||
|
deviceid.c
|
||||||
dedupe.c
|
dedupe.c
|
||||||
demod_9600.c
|
demod_9600.c
|
||||||
demod_afsk.c
|
demod_afsk.c
|
||||||
|
@ -171,6 +172,7 @@ endif()
|
||||||
# decode_aprs
|
# decode_aprs
|
||||||
list(APPEND decode_aprs_SOURCES
|
list(APPEND decode_aprs_SOURCES
|
||||||
decode_aprs.c
|
decode_aprs.c
|
||||||
|
deviceid.c
|
||||||
ais.c
|
ais.c
|
||||||
kiss_frame.c
|
kiss_frame.c
|
||||||
ax25_pad.c
|
ax25_pad.c
|
||||||
|
@ -355,6 +357,7 @@ list(APPEND atest_SOURCES
|
||||||
ax25_pad.c
|
ax25_pad.c
|
||||||
ax25_pad2.c
|
ax25_pad2.c
|
||||||
decode_aprs.c
|
decode_aprs.c
|
||||||
|
deviceid.c
|
||||||
dwgpsnmea.c
|
dwgpsnmea.c
|
||||||
dwgps.c
|
dwgps.c
|
||||||
dwgpsd.c
|
dwgpsd.c
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2017, 2022 John Langner, WB2OSZ
|
// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2017, 2022, 2023 John Langner, WB2OSZ
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -56,7 +56,7 @@
|
||||||
#include "decode_aprs.h"
|
#include "decode_aprs.h"
|
||||||
#include "telemetry.h"
|
#include "telemetry.h"
|
||||||
#include "ais.h"
|
#include "ais.h"
|
||||||
|
#include "deviceid.h"
|
||||||
|
|
||||||
#define TRUE 1
|
#define TRUE 1
|
||||||
#define FALSE 0
|
#define FALSE 0
|
||||||
|
@ -124,7 +124,6 @@ static double get_longitude_9 (char *p, int quiet);
|
||||||
static time_t get_timestamp (decode_aprs_t *A, char *p);
|
static time_t get_timestamp (decode_aprs_t *A, char *p);
|
||||||
static int get_maidenhead (decode_aprs_t *A, char *p);
|
static int get_maidenhead (decode_aprs_t *A, char *p);
|
||||||
static int data_extension_comment (decode_aprs_t *A, char *pdext);
|
static int data_extension_comment (decode_aprs_t *A, char *pdext);
|
||||||
static void decode_tocall (decode_aprs_t *A, char *dest);
|
|
||||||
//static void get_symbol (decode_aprs_t *A, char dti, char *src, char *dest);
|
//static void get_symbol (decode_aprs_t *A, char dti, char *src, char *dest);
|
||||||
static void process_comment (decode_aprs_t *A, char *pstart, int clen);
|
static void process_comment (decode_aprs_t *A, char *pstart, int clen);
|
||||||
|
|
||||||
|
@ -292,7 +291,7 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet, char *third_party_sr
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Application might be in the destination field for most message types.
|
* Device/Application is in the destination field for most packet types.
|
||||||
* MIC-E format has part of location in the destination field.
|
* MIC-E format has part of location in the destination field.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -303,7 +302,7 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet, char *third_party_sr
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
decode_tocall (A, A->g_dest);
|
deviceid_decode_dest (A->g_dest, A->g_mfr, sizeof(A->g_mfr));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1392,7 +1391,6 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
|
||||||
int cust_msg = 0;
|
int cust_msg = 0;
|
||||||
const char *std_text[8] = {"Emergency", "Priority", "Special", "Committed", "Returning", "In Service", "En Route", "Off Duty" };
|
const char *std_text[8] = {"Emergency", "Priority", "Special", "Committed", "Returning", "In Service", "En Route", "Off Duty" };
|
||||||
const char *cust_text[8] = {"Emergency", "Custom-6", "Custom-5", "Custom-4", "Custom-3", "Custom-2", "Custom-1", "Custom-0" };
|
const char *cust_text[8] = {"Emergency", "Custom-6", "Custom-5", "Custom-4", "Custom-3", "Custom-2", "Custom-1", "Custom-0" };
|
||||||
unsigned char *pfirst, *plast;
|
|
||||||
|
|
||||||
strlcpy (A->g_data_type_desc, "MIC-E", sizeof(A->g_data_type_desc));
|
strlcpy (A->g_data_type_desc, "MIC-E", sizeof(A->g_data_type_desc));
|
||||||
|
|
||||||
|
@ -1622,111 +1620,32 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
|
||||||
A->g_course = n;
|
A->g_course = n;
|
||||||
|
|
||||||
|
|
||||||
|
// The rest is a comment which can have other information cryptically embedded.
|
||||||
|
// Remove any trailing CR, which I would argue, violates the protocol spec.
|
||||||
|
// It is essential to keep trailing spaces. e.g. VX-8 suffix is "_ "
|
||||||
|
|
||||||
|
char mcomment[256];
|
||||||
|
strlcpy (mcomment, info + sizeof(struct aprs_mic_e_s), sizeof(mcomment));
|
||||||
|
if (mcomment[strlen(mcomment)-1] == '\r') {
|
||||||
|
mcomment[strlen(mcomment)-1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
/* Now try to pick out manufacturer and other optional items. */
|
/* Now try to pick out manufacturer and other optional items. */
|
||||||
/* The telemetry field, in the original spec, is no longer used. */
|
/* The telemetry field, in the original spec, is no longer used. */
|
||||||
|
|
||||||
strlcpy (A->g_mfr, "Unknown manufacturer", sizeof(A->g_mfr));
|
char trimmed[256]; // Comment with vendor/model removed.
|
||||||
|
deviceid_decode_mice (mcomment, trimmed, sizeof(trimmed), A->g_mfr, sizeof(A->g_mfr));
|
||||||
pfirst = info + sizeof(struct aprs_mic_e_s);
|
|
||||||
plast = info + ilen - 1;
|
|
||||||
|
|
||||||
/* Carriage return character at the end is not mentioned in spec. */
|
|
||||||
/* Remove if found because it messes up extraction of manufacturer. */
|
|
||||||
/* Don't drop trailing space because that is used for Yaesu VX-8. */
|
|
||||||
/* As I recall, the IGate function trims trailing spaces. */
|
|
||||||
/* That would be bad for this particular model. Maybe I'm mistaken? */
|
|
||||||
|
|
||||||
|
|
||||||
if (*plast == '\r') plast--;
|
|
||||||
|
|
||||||
#define isT(c) ((c) == ' ' || (c) == '>' || (c) == ']' || (c) == '`' || (c) == '\'')
|
// Possible altitude. 3 characters followed by }
|
||||||
|
|
||||||
// Last Updated Dec. 2021
|
|
||||||
|
|
||||||
// This does not change very often but I'm wondering if we could parse
|
if (strlen(trimmed) >=4 && trimmed[3] == '}') {
|
||||||
// http://www.aprs.org/aprs12/mic-e-types.txt similar to how we use tocalls.txt.
|
|
||||||
|
|
||||||
// TODO: Use https://github.com/aprsorg/aprs-deviceid rather than hardcoding.
|
A->g_altitude_ft = DW_METERS_TO_FEET((trimmed[0]-33)*91*91 + (trimmed[1]-33)*91 + (trimmed[2]-33) - 10000);
|
||||||
|
|
||||||
if (isT(*pfirst)) {
|
if ( ! isdigit91(trimmed[0]) || ! isdigit91(trimmed[1]) || ! isdigit91(trimmed[2]))
|
||||||
|
|
||||||
// "legacy" formats.
|
|
||||||
|
|
||||||
if (*pfirst == ' ' ) { strlcpy (A->g_mfr, "Original MIC-E", sizeof(A->g_mfr)); pfirst++; }
|
|
||||||
|
|
||||||
else if (*pfirst == '>' && *plast == '=') { strlcpy (A->g_mfr, "Kenwood TH-D72", sizeof(A->g_mfr)); pfirst++; plast--; }
|
|
||||||
else if (*pfirst == '>' && *plast == '^') { strlcpy (A->g_mfr, "Kenwood TH-D74", sizeof(A->g_mfr)); pfirst++; plast--; }
|
|
||||||
else if (*pfirst == '>' && *plast == '&') { strlcpy (A->g_mfr, "Kenwood TH-D75", sizeof(A->g_mfr)); pfirst++; plast--; }
|
|
||||||
else if (*pfirst == '>' ) { strlcpy (A->g_mfr, "Kenwood TH-D7A", sizeof(A->g_mfr)); pfirst++; }
|
|
||||||
|
|
||||||
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; }
|
|
||||||
else if (*pfirst == '`' && *(plast-1) == '_' && *plast == '$') { strlcpy (A->g_mfr, "Yaesu FT1D", sizeof(A->g_mfr)); pfirst++; plast-=2; }
|
|
||||||
else if (*pfirst == '`' && *(plast-1) == '_' && *plast == '%') { strlcpy (A->g_mfr, "Yaesu FTM-400DR", sizeof(A->g_mfr)); pfirst++; plast-=2; }
|
|
||||||
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 == '5') { strlcpy (A->g_mfr, "Yaesu FTM-500D", 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++; }
|
|
||||||
|
|
||||||
// ' should be used for trackers (not message capable).
|
|
||||||
|
|
||||||
else if (*pfirst == '\'' && *(plast-1) == '(' && *plast == '5') { strlcpy (A->g_mfr, "Anytone D578UV", sizeof(A->g_mfr)); pfirst++; plast-=2; }
|
|
||||||
else if (*pfirst == '\'' && *(plast-1) == '(' && *plast == '8') { strlcpy (A->g_mfr, "Anytone D878UV", sizeof(A->g_mfr)); pfirst++; plast-=2; }
|
|
||||||
|
|
||||||
else if (*pfirst == '\'' && *(plast-1) == '|' && *plast == '3') { strlcpy (A->g_mfr, "Byonics TinyTrack3", sizeof(A->g_mfr)); pfirst++; plast-=2; }
|
|
||||||
else if (*pfirst == '\'' && *(plast-1) == '|' && *plast == '4') { strlcpy (A->g_mfr, "Byonics TinyTrack4", sizeof(A->g_mfr)); pfirst++; plast-=2; }
|
|
||||||
|
|
||||||
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, "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, "Unknown OTHER", sizeof(A->g_mfr)); pfirst++; plast-=2; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* An optional altitude is next.
|
|
||||||
* It is three base-91 digits followed by "}".
|
|
||||||
* The TM-D710A might have encoding bug. This was observed:
|
|
||||||
*
|
|
||||||
* KJ4ETP-9>SUUP9Q,KE4OTZ-3,WIDE1*,WIDE2-1,qAR,KI4HDU-2:`oV$n6:>/]"7&}162.475MHz <Knox,TN> clintserman@gmail=
|
|
||||||
* N 35 50.9100, W 083 58.0800, 25 MPH, course 230, alt 945 ft, 162.475MHz
|
|
||||||
*
|
|
||||||
* KJ4ETP-9>SUUP6Y,GRNTOP-3*,WIDE2-1,qAR,KI4HDU-2:`oU~nT >/]<0x9a>xt}162.475MHz <Knox,TN> clintserman@gmail=
|
|
||||||
* Invalid character in MIC-E altitude. Must be in range of '!' to '{'.
|
|
||||||
* N 35 50.6900, W 083 57.9800, 29 MPH, course 204, alt 3280843 ft, 162.475MHz
|
|
||||||
*
|
|
||||||
* KJ4ETP-9>SUUP6Y,N4NEQ-3,K4EGA-1,WIDE2*,qAS,N5CWH-1:`oU~nT >/]?xt}162.475MHz <Knox,TN> clintserman@gmail=
|
|
||||||
* N 35 50.6900, W 083 57.9800, 29 MPH, course 204, alt 808497 ft, 162.475MHz
|
|
||||||
*
|
|
||||||
* KJ4ETP-9>SUUP2W,KE4OTZ-3,WIDE1*,WIDE2-1,qAR,KI4HDU-2:`oV2o"J>/]"7)}162.475MHz <Knox,TN> clintserman@gmail=
|
|
||||||
* N 35 50.2700, W 083 58.2200, 35 MPH, course 246, alt 955 ft, 162.475MHz
|
|
||||||
*
|
|
||||||
* Note the <0x9a> which is outside of the 7-bit ASCII range. Clearly very wrong.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (plast > pfirst && pfirst[3] == '}') {
|
|
||||||
|
|
||||||
A->g_altitude_ft = DW_METERS_TO_FEET((pfirst[0]-33)*91*91 + (pfirst[1]-33)*91 + (pfirst[2]-33) - 10000);
|
|
||||||
|
|
||||||
if ( ! isdigit91(pfirst[0]) || ! isdigit91(pfirst[1]) || ! isdigit91(pfirst[2]))
|
|
||||||
{
|
{
|
||||||
if ( ! A->g_quiet) {
|
if ( ! A->g_quiet) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
@ -1736,12 +1655,13 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
|
||||||
A->g_altitude_ft = G_UNKNOWN;
|
A->g_altitude_ft = G_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
pfirst += 4;
|
process_comment (A, mcomment+4, strlen(mcomment) - 4);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
process_comment (A, (char*)pfirst, (int)(plast - pfirst) + 1);
|
process_comment (A, mcomment, strlen(mcomment));
|
||||||
|
|
||||||
}
|
} // end aprs_mic_e
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------
|
/*------------------------------------------------------------------
|
||||||
|
@ -4251,221 +4171,6 @@ static int data_extension_comment (decode_aprs_t *A, char *pdext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* Function: decode_tocall
|
|
||||||
*
|
|
||||||
* Purpose: Extract application from the destination.
|
|
||||||
*
|
|
||||||
* Inputs: dest - Destination address.
|
|
||||||
* Don't care if SSID is present or not.
|
|
||||||
*
|
|
||||||
* Outputs: A->g_mfr
|
|
||||||
*
|
|
||||||
* Description: For maximum flexibility, we will read the
|
|
||||||
* data file at run time rather than compiling it in.
|
|
||||||
*
|
|
||||||
* For the most recent version, download from:
|
|
||||||
*
|
|
||||||
* http://www.aprs.org/aprs11/tocalls.txt
|
|
||||||
*
|
|
||||||
* Windows version: File must be in current working directory.
|
|
||||||
*
|
|
||||||
* Linux version: Search order is current working directory then
|
|
||||||
* /usr/local/share/direwolf
|
|
||||||
* /usr/share/direwolf/tocalls.txt
|
|
||||||
*
|
|
||||||
* Mac: Like Linux and then
|
|
||||||
* /opt/local/share/direwolf
|
|
||||||
*
|
|
||||||
*------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
// If I was more ambitious, this would dynamically allocate enough
|
|
||||||
// storage based on the file contents. Just stick in a constant for
|
|
||||||
// now. This takes an insignificant amount of space and
|
|
||||||
// I don't anticipate tocalls.txt growing that quickly.
|
|
||||||
// Version 1.4 - add message if too small instead of silently ignoring the rest.
|
|
||||||
|
|
||||||
// Dec. 2016 tocalls.txt has 153 destination addresses.
|
|
||||||
|
|
||||||
#define MAX_TOCALLS 250
|
|
||||||
|
|
||||||
static struct tocalls_s {
|
|
||||||
unsigned char len;
|
|
||||||
char prefix[7];
|
|
||||||
char *description;
|
|
||||||
} tocalls[MAX_TOCALLS];
|
|
||||||
|
|
||||||
static int num_tocalls = 0;
|
|
||||||
|
|
||||||
// Make sure the array is null terminated.
|
|
||||||
// If search order is changed, do the same in symbols.c for consistency.
|
|
||||||
|
|
||||||
static const char *search_locations[] = {
|
|
||||||
(const char *) "tocalls.txt", // CWD
|
|
||||||
(const char *) "data/tocalls.txt", // Windows with CMake
|
|
||||||
(const char *) "../data/tocalls.txt", // ?
|
|
||||||
#ifndef __WIN32__
|
|
||||||
(const char *) "/usr/local/share/direwolf/tocalls.txt",
|
|
||||||
(const char *) "/usr/share/direwolf/tocalls.txt",
|
|
||||||
#endif
|
|
||||||
#if __APPLE__
|
|
||||||
// https://groups.yahoo.com/neo/groups/direwolf_packet/conversations/messages/2458
|
|
||||||
// Adding the /opt/local tree since macports typically installs there. Users might want their
|
|
||||||
// INSTALLDIR (see Makefile.macosx) to mirror that. If so, then we need to search the /opt/local
|
|
||||||
// path as well.
|
|
||||||
(const char *) "/opt/local/share/direwolf/tocalls.txt",
|
|
||||||
#endif
|
|
||||||
(const char *) NULL // Important - Indicates end of list.
|
|
||||||
};
|
|
||||||
|
|
||||||
static int tocall_cmp (const void *px, const void *py)
|
|
||||||
{
|
|
||||||
const struct tocalls_s *x = (struct tocalls_s *)px;
|
|
||||||
const struct tocalls_s *y = (struct tocalls_s *)py;
|
|
||||||
|
|
||||||
if (x->len != y->len) return (y->len - x->len);
|
|
||||||
return (strcmp(x->prefix, y->prefix));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void decode_tocall (decode_aprs_t *A, char *dest)
|
|
||||||
{
|
|
||||||
FILE *fp = 0;
|
|
||||||
int n = 0;
|
|
||||||
static int first_time = 1;
|
|
||||||
char stuff[100];
|
|
||||||
char *p = NULL;
|
|
||||||
char *r = NULL;
|
|
||||||
|
|
||||||
//dw_printf("debug: decode_tocall(\"%s\")\n", dest);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Extract the calls and descriptions from the file.
|
|
||||||
*
|
|
||||||
* Use only lines with exactly these formats:
|
|
||||||
*
|
|
||||||
* APN Network nodes, digis, etc
|
|
||||||
* APWWxx APRSISCE win32 version
|
|
||||||
* | | |
|
|
||||||
* 00000000001111111111
|
|
||||||
* 01234567890123456789...
|
|
||||||
*
|
|
||||||
* Matching will be with only leading upper case and digits.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// TODO: Look for this in multiple locations.
|
|
||||||
// For example, if application was installed in /usr/local/bin,
|
|
||||||
// we might want to put this in /usr/local/share/aprs
|
|
||||||
|
|
||||||
// If search strategy changes, be sure to keep symbols_init in sync.
|
|
||||||
|
|
||||||
if (first_time) {
|
|
||||||
|
|
||||||
n = 0;
|
|
||||||
fp = NULL;
|
|
||||||
do {
|
|
||||||
if(search_locations[n] == NULL) break;
|
|
||||||
fp = fopen(search_locations[n++], "r");
|
|
||||||
} while (fp == NULL);
|
|
||||||
|
|
||||||
if (fp != NULL) {
|
|
||||||
|
|
||||||
while (fgets(stuff, sizeof(stuff), fp) != NULL && num_tocalls < MAX_TOCALLS) {
|
|
||||||
|
|
||||||
p = stuff + strlen(stuff) - 1;
|
|
||||||
while (p >= stuff && (*p == '\r' || *p == '\n')) {
|
|
||||||
*p-- = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
// dw_printf("debug: %s\n", stuff);
|
|
||||||
|
|
||||||
if (stuff[0] == ' ' &&
|
|
||||||
stuff[4] == ' ' &&
|
|
||||||
stuff[5] == ' ' &&
|
|
||||||
stuff[6] == 'A' &&
|
|
||||||
stuff[7] == 'P' &&
|
|
||||||
stuff[12] == ' ' &&
|
|
||||||
stuff[13] == ' ' ) {
|
|
||||||
|
|
||||||
p = stuff + 6;
|
|
||||||
r = tocalls[num_tocalls].prefix;
|
|
||||||
while (isupper((int)(*p)) || isdigit((int)(*p))) {
|
|
||||||
*r++ = *p++;
|
|
||||||
}
|
|
||||||
*r = '\0';
|
|
||||||
if (strlen(tocalls[num_tocalls].prefix) > 2) {
|
|
||||||
tocalls[num_tocalls].description = strdup(stuff+14);
|
|
||||||
tocalls[num_tocalls].len = strlen(tocalls[num_tocalls].prefix);
|
|
||||||
// dw_printf("debug %d: %d '%s' -> '%s'\n", num_tocalls, tocalls[num_tocalls].len, tocalls[num_tocalls].prefix, tocalls[num_tocalls].description);
|
|
||||||
|
|
||||||
num_tocalls++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (stuff[0] == ' ' &&
|
|
||||||
stuff[1] == 'A' &&
|
|
||||||
stuff[2] == 'P' &&
|
|
||||||
isupper((int)(stuff[3])) &&
|
|
||||||
stuff[4] == ' ' &&
|
|
||||||
stuff[5] == ' ' &&
|
|
||||||
stuff[6] == ' ' &&
|
|
||||||
stuff[12] == ' ' &&
|
|
||||||
stuff[13] == ' ' ) {
|
|
||||||
|
|
||||||
p = stuff + 1;
|
|
||||||
r = tocalls[num_tocalls].prefix;
|
|
||||||
while (isupper((int)(*p)) || isdigit((int)(*p))) {
|
|
||||||
*r++ = *p++;
|
|
||||||
}
|
|
||||||
*r = '\0';
|
|
||||||
if (strlen(tocalls[num_tocalls].prefix) > 2) {
|
|
||||||
tocalls[num_tocalls].description = strdup(stuff+14);
|
|
||||||
tocalls[num_tocalls].len = strlen(tocalls[num_tocalls].prefix);
|
|
||||||
// dw_printf("debug %d: %d '%s' -> '%s'\n", num_tocalls, tocalls[num_tocalls].len, tocalls[num_tocalls].prefix, tocalls[num_tocalls].description);
|
|
||||||
|
|
||||||
num_tocalls++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (num_tocalls == MAX_TOCALLS) { // oops. might have discarded some.
|
|
||||||
text_color_set(DW_COLOR_ERROR);
|
|
||||||
dw_printf("MAX_TOCALLS needs to be larger than %d to handle contents of 'tocalls.txt'.\n", MAX_TOCALLS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sort by decreasing length so the search will go
|
|
||||||
* from most specific to least specific.
|
|
||||||
* Example: APY350 or APY008 would match those specific
|
|
||||||
* models before getting to the more generic APY.
|
|
||||||
*/
|
|
||||||
|
|
||||||
qsort (tocalls, num_tocalls, sizeof(struct tocalls_s), tocall_cmp);
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ( ! A->g_quiet) {
|
|
||||||
text_color_set(DW_COLOR_ERROR);
|
|
||||||
dw_printf("Warning: Could not open 'tocalls.txt'.\n");
|
|
||||||
dw_printf("System types in the destination field will not be decoded.\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
first_time = 0;
|
|
||||||
|
|
||||||
//for (n=0; n<num_tocalls; n++) {
|
|
||||||
// dw_printf("sorted %d: %d '%s' -> '%s'\n", n, tocalls[n].len, tocalls[n].prefix, tocalls[n].description);
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for (n=0; n<num_tocalls; n++) {
|
|
||||||
if (strncmp(dest, tocalls[n].prefix, tocalls[n].len) == 0) {
|
|
||||||
strlcpy (A->g_mfr, tocalls[n].description, sizeof(A->g_mfr));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* end decode_tocall */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -4513,7 +4218,7 @@ static void substr_se (char *dest, const char *src, int start, int endp1)
|
||||||
* clen - Length of comment or -1 to take it all.
|
* clen - Length of comment or -1 to take it all.
|
||||||
*
|
*
|
||||||
* Outputs: A->g_telemetry - Base 91 telemetry |ss1122|
|
* Outputs: A->g_telemetry - Base 91 telemetry |ss1122|
|
||||||
* A->g_altitude_ft - from /A=123456
|
* A->g_altitude_ft - from /A=123456 or /A=-12345
|
||||||
* A->g_lat - Might be adjusted from !DAO!
|
* A->g_lat - Might be adjusted from !DAO!
|
||||||
* A->g_lon - Might be adjusted from !DAO!
|
* A->g_lon - Might be adjusted from !DAO!
|
||||||
* A->g_aprstt_loc - Private extension to !DAO!
|
* A->g_aprstt_loc - Private extension to !DAO!
|
||||||
|
@ -4543,6 +4248,10 @@ static void substr_se (char *dest, const char *src, int start, int endp1)
|
||||||
* Protocol reference, end of chapter 6.
|
* Protocol reference, end of chapter 6.
|
||||||
*
|
*
|
||||||
* /A=123456 Altitude
|
* /A=123456 Altitude
|
||||||
|
* /A=-12345 Enhancement - There are many places on the earth's
|
||||||
|
* surface but the APRS spec has no provision for negative
|
||||||
|
* numbers. I propose having 5 digits for a consistent
|
||||||
|
* field width. 6 would be excessive.
|
||||||
*
|
*
|
||||||
* What can appear in a comment?
|
* What can appear in a comment?
|
||||||
*
|
*
|
||||||
|
@ -4708,7 +4417,7 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen)
|
||||||
dw_printf("%s:%d: %s\n", __FILE__, __LINE__, emsg);
|
dw_printf("%s:%d: %s\n", __FILE__, __LINE__, emsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
e = regcomp (&alt_re, "/A=[0-9][0-9][0-9][0-9][0-9][0-9]", REG_EXTENDED);
|
e = regcomp (&alt_re, "/A=[0-9-][0-9][0-9][0-9][0-9][0-9]", REG_EXTENDED);
|
||||||
if (e) {
|
if (e) {
|
||||||
regerror (e, &alt_re, emsg, sizeof(emsg));
|
regerror (e, &alt_re, emsg, sizeof(emsg));
|
||||||
dw_printf("%s:%d: %s\n", __FILE__, __LINE__, emsg);
|
dw_printf("%s:%d: %s\n", __FILE__, __LINE__, emsg);
|
||||||
|
@ -5068,7 +4777,7 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Altitude in feet. /A=123456
|
* Altitude in feet. /A=123456 or /A=-12345
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (regexec (&alt_re, A->g_comment, MAXMATCH, match, 0) == 0)
|
if (regexec (&alt_re, A->g_comment, MAXMATCH, match, 0) == 0)
|
||||||
|
@ -5186,7 +4895,7 @@ static void process_comment (decode_aprs_t *A, char *pstart, int clen)
|
||||||
*
|
*
|
||||||
* Function: main
|
* Function: main
|
||||||
*
|
*
|
||||||
* Purpose: Main program for standalone test program.
|
* Purpose: Main program for standalone application to parse and explain APRS packets.
|
||||||
*
|
*
|
||||||
* Inputs: stdin for raw data to decode.
|
* Inputs: stdin for raw data to decode.
|
||||||
* This is in the usual display format either from
|
* This is in the usual display format either from
|
||||||
|
@ -5332,6 +5041,7 @@ int main (int argc, char *argv[])
|
||||||
// If you don't like the text colors, use 0 instead of 1 here.
|
// If you don't like the text colors, use 0 instead of 1 here.
|
||||||
text_color_init(1);
|
text_color_init(1);
|
||||||
text_color_set(DW_COLOR_INFO);
|
text_color_set(DW_COLOR_INFO);
|
||||||
|
deviceid_init();
|
||||||
|
|
||||||
while (fgets(stuff, sizeof(stuff), stdin) != NULL)
|
while (fgets(stuff, sizeof(stuff), stdin) != NULL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,660 @@
|
||||||
|
//
|
||||||
|
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2023 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
|
||||||
|
// the Free Software Foundation, either version 2 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* File: deviceid.c
|
||||||
|
*
|
||||||
|
* Purpose: Determine the device identifier from the destination field,
|
||||||
|
* or from prefix/suffix for MIC-E format.
|
||||||
|
*
|
||||||
|
* Description: Orginally this used the tocalls.txt file and was part of decode_aprs.c.
|
||||||
|
* For release 1.8, we use tocalls.yaml and this is split into a separate file.
|
||||||
|
*
|
||||||
|
*------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
//#define TEST 1 // Standalone test. $ gcc -DTEST deviceid.c && ./a.out
|
||||||
|
|
||||||
|
|
||||||
|
#if TEST
|
||||||
|
#define HAVE_STRLCPY 1 // prevent defining in direwolf.h
|
||||||
|
#define HAVE_STRLCAT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "direwolf.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "deviceid.h"
|
||||||
|
#include "textcolor.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void unquote (int line, char *pin, char *pout);
|
||||||
|
static int tocall_cmp (const void *px, const void *py);
|
||||||
|
static int mice_cmp (const void *px, const void *py);
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Function: main
|
||||||
|
*
|
||||||
|
* Purpose: A little self-test used during development.
|
||||||
|
*
|
||||||
|
* Description: Read the yaml file. Decipher a few typical values.
|
||||||
|
*
|
||||||
|
*------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if TEST
|
||||||
|
// So we don't need to link with any other files.
|
||||||
|
#define dw_printf printf
|
||||||
|
void text_color_set(dw_color_t) { return; }
|
||||||
|
void strlcpy(char *dst, char *src, size_t dlen) {
|
||||||
|
strcpy (dst, src);
|
||||||
|
}
|
||||||
|
void strlcat(char *dst, char *src, size_t dlen) {
|
||||||
|
strcat (dst, src);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char device[80];
|
||||||
|
char comment_out[80];
|
||||||
|
|
||||||
|
deviceid_init ();
|
||||||
|
|
||||||
|
dw_printf ("\n");
|
||||||
|
dw_printf ("Testing ...\n");
|
||||||
|
|
||||||
|
// MIC-E Legacy (really Kenwood).
|
||||||
|
|
||||||
|
deviceid_decode_mice (">Comment", comment_out, sizeof(comment_out), device, sizeof(device));
|
||||||
|
dw_printf ("%s %s\n", comment_out, device);
|
||||||
|
assert (strcmp(comment_out, "Comment") == 0);
|
||||||
|
assert (strcmp(device, "Kenwood TH-D7A") == 0);
|
||||||
|
|
||||||
|
deviceid_decode_mice (">Comment^", comment_out, sizeof(comment_out), device, sizeof(device));
|
||||||
|
dw_printf ("%s %s\n", comment_out, device);
|
||||||
|
assert (strcmp(comment_out, "Comment") == 0);
|
||||||
|
assert (strcmp(device, "Kenwood TH-D74") == 0);
|
||||||
|
|
||||||
|
deviceid_decode_mice ("]Comment", comment_out, sizeof(comment_out), device, sizeof(device));
|
||||||
|
dw_printf ("%s %s\n", comment_out, device);
|
||||||
|
assert (strcmp(comment_out, "Comment") == 0);
|
||||||
|
assert (strcmp(device, "Kenwood TM-D700") == 0);
|
||||||
|
|
||||||
|
deviceid_decode_mice ("]Comment=", comment_out, sizeof(comment_out), device, sizeof(device));
|
||||||
|
dw_printf ("%s %s\n", comment_out, device);
|
||||||
|
assert (strcmp(comment_out, "Comment") == 0);
|
||||||
|
assert (strcmp(device, "Kenwood TM-D710") == 0);
|
||||||
|
|
||||||
|
|
||||||
|
// Modern MIC-E.
|
||||||
|
|
||||||
|
deviceid_decode_mice ("`Comment_\"", comment_out, sizeof(comment_out), device, sizeof(device));
|
||||||
|
dw_printf ("%s %s\n", comment_out, device);
|
||||||
|
assert (strcmp(comment_out, "Comment") == 0);
|
||||||
|
assert (strcmp(device, "Yaesu FTM-350") == 0);
|
||||||
|
|
||||||
|
deviceid_decode_mice ("`Comment_ ", comment_out, sizeof(comment_out), device, sizeof(device));
|
||||||
|
dw_printf ("%s %s\n", comment_out, device);
|
||||||
|
assert (strcmp(comment_out, "Comment") == 0);
|
||||||
|
assert (strcmp(device, "Yaesu VX-8") == 0);
|
||||||
|
|
||||||
|
deviceid_decode_mice ("'Comment|3", comment_out, sizeof(comment_out), device, sizeof(device));
|
||||||
|
dw_printf ("%s %s\n", comment_out, device);
|
||||||
|
assert (strcmp(comment_out, "Comment") == 0);
|
||||||
|
assert (strcmp(device, "Byonics TinyTrak3") == 0);
|
||||||
|
|
||||||
|
deviceid_decode_mice ("Comment", comment_out, sizeof(comment_out), device, sizeof(device));
|
||||||
|
dw_printf ("%s %s\n", comment_out, device);
|
||||||
|
assert (strcmp(comment_out, "Comment") == 0);
|
||||||
|
assert (strcmp(device, "UNKNOWN vendor/model") == 0);
|
||||||
|
|
||||||
|
|
||||||
|
// Tocall
|
||||||
|
|
||||||
|
deviceid_decode_dest ("APDW18", device, sizeof(device));
|
||||||
|
dw_printf ("%s\n", device);
|
||||||
|
assert (strcmp(device, "WB2OSZ DireWolf") == 0);
|
||||||
|
|
||||||
|
deviceid_decode_dest ("APD123", device, sizeof(device));
|
||||||
|
dw_printf ("%s\n", device);
|
||||||
|
assert (strcmp(device, "Open Source aprsd") == 0);
|
||||||
|
|
||||||
|
// null for Vendor.
|
||||||
|
deviceid_decode_dest ("APAX", device, sizeof(device));
|
||||||
|
dw_printf ("%s\n", device);
|
||||||
|
assert (strcmp(device, "AFilterX") == 0);
|
||||||
|
|
||||||
|
deviceid_decode_dest ("APA123", device, sizeof(device));
|
||||||
|
dw_printf ("%s\n", device);
|
||||||
|
assert (strcmp(device, "UNKNOWN vendor/model") == 0);
|
||||||
|
|
||||||
|
dw_printf ("\n");
|
||||||
|
dw_printf ("Success!\n");
|
||||||
|
|
||||||
|
exit (EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // TEST
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Structures to hold mapping from encoded form to vendor and model.
|
||||||
|
// The .yaml file has two separate sections for MIC-E but they can
|
||||||
|
// both be handled as a single more general case.
|
||||||
|
|
||||||
|
struct mice {
|
||||||
|
char prefix[4]; // The legacy form has 1 prefix character.
|
||||||
|
// The newer form has none. (more accurately ` or ')
|
||||||
|
char suffix[4]; // The legacy form has 0 or 1.
|
||||||
|
// The newer form has 2.
|
||||||
|
char *vendor;
|
||||||
|
char *model;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tocalls {
|
||||||
|
char tocall[8]; // Up to 6 characters. Some may have wildcards at the end.
|
||||||
|
// Most often they are trailing "??" or "?" or "???" in one case.
|
||||||
|
// Sometimes there is trailing "nnn". Does that imply digits only?
|
||||||
|
// Sometimes we see a trailing "*". Is "*" different than "?"?
|
||||||
|
// There are a couple bizzare cases like APnnnD which can
|
||||||
|
// create an ambigious situation. APMPAD, APRFGD, APY0[125]D.
|
||||||
|
// Screw them if they can't follow the rules. I'm not putting in a special case.
|
||||||
|
char *vendor;
|
||||||
|
char *model;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct mice *pmice = NULL; // Pointer to array.
|
||||||
|
static int mice_count = 0; // Number of allocated elements.
|
||||||
|
static int mice_index = -1; // Current index for filling in.
|
||||||
|
|
||||||
|
static struct tocalls *ptocalls = NULL; // Pointer to array.
|
||||||
|
static int tocalls_count = 0; // Number of allocated elements.
|
||||||
|
static int tocalls_index = -1; // Current index for filling in.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Function: deviceid_init
|
||||||
|
*
|
||||||
|
* Purpose: Called once at startup to read the tocalls.yaml file which was obtained from
|
||||||
|
* https://github.com/aprsorg/aprs-deviceid .
|
||||||
|
*
|
||||||
|
* Inputs: tocalls.yaml with OS specific directory search list.
|
||||||
|
*
|
||||||
|
* Outputs: static variables listed above.
|
||||||
|
*
|
||||||
|
* Description: For maximum flexibility, we will read the
|
||||||
|
* data file at run time rather than compiling it in.
|
||||||
|
*
|
||||||
|
*------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// Make sure the array is null terminated.
|
||||||
|
// If search order is changed, do the same in symbols.c for consistency.
|
||||||
|
// fopen is perfectly happy with / in file path when running on Windows.
|
||||||
|
|
||||||
|
static const char *search_locations[] = {
|
||||||
|
(const char *) "tocalls.yaml", // Current working directory
|
||||||
|
(const char *) "data/tocalls.yaml", // Windows with CMake
|
||||||
|
(const char *) "../data/tocalls.yaml", // Source tree
|
||||||
|
#ifndef __WIN32__
|
||||||
|
(const char *) "/usr/local/share/direwolf/tocalls.yaml",
|
||||||
|
(const char *) "/usr/share/direwolf/tocalls.yaml",
|
||||||
|
#endif
|
||||||
|
#if __APPLE__
|
||||||
|
// https://groups.yahoo.com/neo/groups/direwolf_packet/conversations/messages/2458
|
||||||
|
// Adding the /opt/local tree since macports typically installs there. Users might want their
|
||||||
|
// INSTALLDIR (see Makefile.macosx) to mirror that. If so, then we need to search the /opt/local
|
||||||
|
// path as well.
|
||||||
|
(const char *) "/opt/local/share/direwolf/tocalls.yaml",
|
||||||
|
#endif
|
||||||
|
(const char *) NULL // Important - Indicates end of list.
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void deviceid_init(void)
|
||||||
|
{
|
||||||
|
FILE *fp = NULL;
|
||||||
|
for (int n = 0; search_locations[n] != NULL && fp == NULL; n++) {
|
||||||
|
dw_printf ("Trying %s\n", search_locations[n]);
|
||||||
|
fp = fopen(search_locations[n], "r");
|
||||||
|
#if TEST
|
||||||
|
if (fp != NULL) {
|
||||||
|
dw_printf ("Opened %s\n", search_locations[n]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
if (fp == NULL) {
|
||||||
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
dw_printf("Could not open any of these file locations:\n");
|
||||||
|
for (int n = 0; search_locations[n] != NULL; n++) {
|
||||||
|
dw_printf (" %s\n", search_locations[n]);
|
||||||
|
}
|
||||||
|
dw_printf("It won't be possible to extract device identifiers from packets.\n");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Read file first time to get number of items.
|
||||||
|
// Allocate required space.
|
||||||
|
// Rewind.
|
||||||
|
// Read file second time to gather data.
|
||||||
|
|
||||||
|
enum { no_section, mice_section, tocalls_section} section = no_section;
|
||||||
|
char stuff[80];
|
||||||
|
|
||||||
|
for (int pass = 1; pass <=2; pass++) {
|
||||||
|
int line = 0; // Line number within file.
|
||||||
|
|
||||||
|
while (fgets(stuff, sizeof(stuff), fp)) {
|
||||||
|
line++;
|
||||||
|
|
||||||
|
// Remove trailing CR/LF or spaces.
|
||||||
|
char *p = stuff + strlen(stuff) - 1;
|
||||||
|
while (p >= (char*)stuff && (*p == '\r' || *p == '\n' || *p == ' ')) {
|
||||||
|
*p-- = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore comment lines.
|
||||||
|
if (stuff[0] == '#') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if TEST
|
||||||
|
//dw_printf ("%d: %s\n", line, stuff);
|
||||||
|
#endif
|
||||||
|
// This is not very robust; everything better be in exactly the right format.
|
||||||
|
|
||||||
|
if (strncmp(stuff, "mice:", strlen("mice:")) == 0) {
|
||||||
|
section = mice_section;
|
||||||
|
#if TEST
|
||||||
|
dw_printf ("Pass %d, line %d, MIC-E section\n", pass, line);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (strncmp(stuff, "micelegacy:", strlen("micelegacy:")) == 0) {
|
||||||
|
section = mice_section; // treat both same.
|
||||||
|
#if TEST
|
||||||
|
dw_printf ("Pass %d, line %d, Legacy MIC-E section\n", pass, line);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (strncmp(stuff, "tocalls:", strlen("tocalls:")) == 0) {
|
||||||
|
section = tocalls_section;
|
||||||
|
#if TEST
|
||||||
|
dw_printf ("Pass %d, line %d, TOCALLS section\n", pass, line);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// The first property of an item is preceded by " - ".
|
||||||
|
|
||||||
|
if (pass == 1 && strncmp(stuff, " - ", 3) == 0) {
|
||||||
|
switch (section) {
|
||||||
|
case no_section: break;
|
||||||
|
case mice_section: mice_count++; break;
|
||||||
|
case tocalls_section: tocalls_count++; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pass == 2) {
|
||||||
|
switch (section) {
|
||||||
|
case no_section:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case mice_section:
|
||||||
|
if (strncmp(stuff, " - ", 3) == 0) {
|
||||||
|
mice_index++;
|
||||||
|
assert (mice_index >= 0 && mice_index < mice_count);
|
||||||
|
}
|
||||||
|
if (strncmp(stuff+3, "prefix: ", strlen("prefix: ")) == 0) {
|
||||||
|
unquote (line, stuff+3+8, pmice[mice_index].prefix);
|
||||||
|
}
|
||||||
|
else if (strncmp(stuff+3, "suffix: ", strlen("suffix: ")) == 0) {
|
||||||
|
unquote (line, stuff+3+8, pmice[mice_index].suffix);
|
||||||
|
}
|
||||||
|
else if (strncmp(stuff+3, "vendor: ", strlen("vendor: ")) == 0) {
|
||||||
|
pmice[mice_index].vendor = strdup(stuff+3+8);
|
||||||
|
}
|
||||||
|
else if (strncmp(stuff+3, "model: ", strlen("model: ")) == 0) {
|
||||||
|
pmice[mice_index].model = strdup(stuff+3+7);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tocalls_section:
|
||||||
|
if (strncmp(stuff, " - ", 3) == 0) {
|
||||||
|
tocalls_index++;
|
||||||
|
assert (tocalls_index >= 0 && tocalls_index < tocalls_count);
|
||||||
|
}
|
||||||
|
if (strncmp(stuff+3, "tocall: ", strlen("tocall: ")) == 0) {
|
||||||
|
// Remove trailing wildcard characters ? * n
|
||||||
|
char *r = stuff + strlen(stuff) - 1;
|
||||||
|
while (r >= (char*)stuff && (*r == '?' || *r == '*' || *r == 'n')) {
|
||||||
|
*r-- = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
strlcpy (ptocalls[tocalls_index].tocall, stuff+3+8, sizeof(ptocalls[tocalls_index].tocall));
|
||||||
|
|
||||||
|
// Remove trailing CR/LF or spaces.
|
||||||
|
char *p = stuff + strlen(stuff) - 1;
|
||||||
|
while (p >= (char*)stuff && (*p == '\r' || *p == '\n' || *p == ' ')) {
|
||||||
|
*p-- = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strncmp(stuff+3, "vendor: ", strlen("vendor: ")) == 0) {
|
||||||
|
ptocalls[tocalls_index].vendor = strdup(stuff+3+8);
|
||||||
|
}
|
||||||
|
else if (strncmp(stuff+3, "model: ", strlen("model: ")) == 0) {
|
||||||
|
ptocalls[tocalls_index].model = strdup(stuff+3+7);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // while(fgets
|
||||||
|
|
||||||
|
if (pass == 1) {
|
||||||
|
#if TEST
|
||||||
|
dw_printf ("deviceid sizes %d %d\n", mice_count, tocalls_count);
|
||||||
|
#endif
|
||||||
|
pmice = calloc(sizeof(struct mice), mice_count);
|
||||||
|
ptocalls = calloc(sizeof(struct tocalls), tocalls_count);
|
||||||
|
|
||||||
|
rewind (fp);
|
||||||
|
section = no_section;
|
||||||
|
}
|
||||||
|
} // for pass = 1 or 2
|
||||||
|
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
assert (mice_index == mice_count - 1);
|
||||||
|
assert (tocalls_index == tocalls_count - 1);
|
||||||
|
|
||||||
|
|
||||||
|
// MIC-E Legacy needs to be sorted so those with suffix come first.
|
||||||
|
|
||||||
|
qsort (pmice, mice_count, sizeof(struct mice), mice_cmp);
|
||||||
|
|
||||||
|
|
||||||
|
// Sort tocalls by decreasing length so the search will go from most specific to least specific.
|
||||||
|
// Example: APY350 or APY008 would match those specific models before getting to the more generic APY.
|
||||||
|
|
||||||
|
qsort (ptocalls, tocalls_count, sizeof(struct tocalls), tocall_cmp);
|
||||||
|
|
||||||
|
|
||||||
|
#if TEST
|
||||||
|
dw_printf ("MIC-E:\n");
|
||||||
|
for (int i = 0; i < mice_count; i++) {
|
||||||
|
dw_printf ("%s %s %s\n", pmice[i].suffix, pmice[i].vendor, pmice[i].model);
|
||||||
|
}
|
||||||
|
dw_printf ("TOCALLS:\n");
|
||||||
|
for (int i = 0; i < tocalls_count; i++) {
|
||||||
|
dw_printf ("%s %s %s\n", ptocalls[i].tocall, ptocalls[i].vendor, ptocalls[i].model);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
} // end deviceid_init
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Function: unquote
|
||||||
|
*
|
||||||
|
* Purpose: Remove surrounding quotes and undo any escapes.
|
||||||
|
*
|
||||||
|
* Inputs: line - File line number for error message.
|
||||||
|
*
|
||||||
|
* in - String with quotes. Might contain \ escapes.
|
||||||
|
*
|
||||||
|
* Outputs: out - Quotes and escapes removed.
|
||||||
|
* Limited to 2 characters to avoid buffer overflow.
|
||||||
|
*
|
||||||
|
* Examples: in out
|
||||||
|
* "_#" _#
|
||||||
|
* "_\"" _"
|
||||||
|
* "=" =
|
||||||
|
*
|
||||||
|
*------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void unquote (int line, char *pin, char *pout)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
*pout = '\0';
|
||||||
|
if (*pin != '"') {
|
||||||
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
dw_printf("Missing leading \" for %s on line %d.\n", pin, line);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pin++;
|
||||||
|
while (*pin != '\0' && *pin != '\"' && count < 2) {
|
||||||
|
if (*pin == '\\') {
|
||||||
|
pin++;
|
||||||
|
}
|
||||||
|
*pout++ = *pin++;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
*pout = '\0';
|
||||||
|
|
||||||
|
if (*pin != '"') {
|
||||||
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
dw_printf("Missing trailing \" or string too long on line %d.\n", line);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used to sort the tocalls by length.
|
||||||
|
// When length is equal, alphabetically.
|
||||||
|
|
||||||
|
static int tocall_cmp (const void *px, const void *py)
|
||||||
|
{
|
||||||
|
const struct tocalls *x = (struct tocalls *)px;
|
||||||
|
const struct tocalls *y = (struct tocalls *)py;
|
||||||
|
|
||||||
|
if (strlen(x->tocall) != strlen(y->tocall)) {
|
||||||
|
return (strlen(y->tocall) - strlen(x->tocall));
|
||||||
|
}
|
||||||
|
return (strcmp(x->tocall, y->tocall));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used to sort the suffixes by length.
|
||||||
|
// Longer at the top.
|
||||||
|
// Example check for >xxx^ before >xxx .
|
||||||
|
|
||||||
|
static int mice_cmp (const void *px, const void *py)
|
||||||
|
{
|
||||||
|
const struct mice *x = (struct mice *)px;
|
||||||
|
const struct mice *y = (struct mice *)py;
|
||||||
|
|
||||||
|
return (strlen(y->suffix) - strlen(x->suffix));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Function: deviceid_decode_dest
|
||||||
|
*
|
||||||
|
* Purpose: Find vendor/model for destination address of form APxxxx.
|
||||||
|
*
|
||||||
|
* Inputs: dest - Destination address. No SSID.
|
||||||
|
*
|
||||||
|
* device_size - Amount of space available for result to avoid buffer overflow.
|
||||||
|
*
|
||||||
|
* Outputs: device - Vendor and model.
|
||||||
|
*
|
||||||
|
* Description: With the exception of MIC-E format, we expect to find the vendor/model in the
|
||||||
|
* AX.25 destination field. The form should be APxxxx.
|
||||||
|
*
|
||||||
|
* Search the list looking for the maximum length match.
|
||||||
|
* For example,
|
||||||
|
* APXR = Xrouter
|
||||||
|
* APX = Xastir
|
||||||
|
*
|
||||||
|
*------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void deviceid_decode_dest (char *dest, char *device, size_t device_size)
|
||||||
|
{
|
||||||
|
*device = '\0';
|
||||||
|
|
||||||
|
if (ptocalls == NULL) {
|
||||||
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
dw_printf("deviceid_decode_dest called without any deviceid data.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int n = 0; n < tocalls_count; n++) {
|
||||||
|
if (strncmp(dest, ptocalls[n].tocall, strlen(ptocalls[n].tocall)) == 0) {
|
||||||
|
|
||||||
|
if (ptocalls[n].vendor != NULL) {
|
||||||
|
strlcpy (device, ptocalls[n].vendor, device_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptocalls[n].vendor != NULL && ptocalls[n].model != NULL) {
|
||||||
|
strlcat (device, " ", device_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptocalls[n].model != NULL) {
|
||||||
|
strlcat (device, ptocalls[n].model, device_size);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strlcpy (device, "UNKNOWN vendor/model", device_size);
|
||||||
|
|
||||||
|
} // end deviceid_decode_dest
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Function: deviceid_decode_mice
|
||||||
|
*
|
||||||
|
* Purpose: Find vendor/model for MIC-E comment.
|
||||||
|
*
|
||||||
|
* Inputs: comment - MIC-E comment that might have vendor/model encoded as
|
||||||
|
* a prefix and/or suffix.
|
||||||
|
*
|
||||||
|
* trimmed_size - Amount of space available for result to avoid buffer overflow.
|
||||||
|
*
|
||||||
|
* device_size - Amount of space available for result to avoid buffer overflow.
|
||||||
|
*
|
||||||
|
* Outputs: trimmed - Final comment with device vendor/model removed.
|
||||||
|
*
|
||||||
|
* device - Vendor and model.
|
||||||
|
*
|
||||||
|
* Description: This has a tortured history.
|
||||||
|
*
|
||||||
|
* The Kenwood TH-D7A put ">" at the beginning of the comment.
|
||||||
|
* The Kenwood TM-D700 put "]" at the beginning of the comment.
|
||||||
|
* Later Kenwood models also added a single suffix character
|
||||||
|
* using a character very unlikely to appear at the end of a comment.
|
||||||
|
*
|
||||||
|
* The later convention, used by everyone else, is to have a prefix of ` or '
|
||||||
|
* and a suffix of two characters. The suffix characters need to be
|
||||||
|
* something very unlikely to be found at the end of a comment.
|
||||||
|
*
|
||||||
|
* A receiving device is expected to remove those extra characters
|
||||||
|
* before displaying the comment.
|
||||||
|
*
|
||||||
|
* References: http://www.aprs.org/aprs12/mic-e-types.txt
|
||||||
|
* http://www.aprs.org/aprs12/mic-e-examples.txt
|
||||||
|
*
|
||||||
|
*------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// The strncmp documentation doesn't mention behavior if length is zero.
|
||||||
|
// Do our own just to be safe.
|
||||||
|
|
||||||
|
static inline int strncmp_z (char *a, char *b, size_t len)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
if (len > 0) {
|
||||||
|
result = strncmp(a, b, len);
|
||||||
|
}
|
||||||
|
//dw_printf ("Comparing '%s' and '%s' len %d result %d\n", a, b, len, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void deviceid_decode_mice (char *comment, char *trimmed, size_t trimmed_size, char *device, size_t device_size)
|
||||||
|
{
|
||||||
|
*device = '\0';
|
||||||
|
|
||||||
|
if (ptocalls == NULL) {
|
||||||
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
dw_printf("deviceid_decode_mice called without any deviceid data.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// The Legacy format has an explicit prefix in the table.
|
||||||
|
// For others, it must be ` or ' to indicate whether messaging capable.
|
||||||
|
|
||||||
|
for (int n = 0; n < mice_count; n++) {
|
||||||
|
if ((strlen(pmice[n].prefix) != 0 && // Legacy
|
||||||
|
strncmp_z(comment, // prefix from table
|
||||||
|
pmice[n].prefix,
|
||||||
|
strlen(pmice[n].prefix)) == 0 &&
|
||||||
|
strncmp_z(comment + strlen(comment) - strlen(pmice[n].suffix), //suffix
|
||||||
|
pmice[n].suffix,
|
||||||
|
strlen(pmice[n].suffix)) == 0) ||
|
||||||
|
|
||||||
|
(strlen(pmice[n].prefix) == 0 && // Later
|
||||||
|
(comment[0] == '`' || comment[0] == '\'') && // prefix ` or '
|
||||||
|
strncmp_z(comment + strlen(comment) - strlen(pmice[n].suffix), //suffix
|
||||||
|
pmice[n].suffix,
|
||||||
|
strlen(pmice[n].suffix)) == 0) ) {
|
||||||
|
|
||||||
|
if (pmice[n].vendor != NULL) {
|
||||||
|
strlcpy (device, pmice[n].vendor, device_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pmice[n].vendor != NULL && pmice[n].model != NULL) {
|
||||||
|
strlcat (device, " ", device_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pmice[n].model != NULL) {
|
||||||
|
strlcat (device, pmice[n].model, device_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove any prefix/suffix and return what remains.
|
||||||
|
|
||||||
|
strlcpy (trimmed, comment + 1, trimmed_size);
|
||||||
|
trimmed[strlen(comment) - 1 - strlen(pmice[n].suffix)] = '\0';
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Not found.
|
||||||
|
|
||||||
|
strlcpy (device, "UNKNOWN vendor/model", device_size);
|
||||||
|
|
||||||
|
} // end deviceid_decode_mice
|
||||||
|
|
||||||
|
// end deviceid.c
|
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
// deviceid.h
|
||||||
|
|
||||||
|
void deviceid_init(void);
|
||||||
|
void deviceid_decode_dest (char *dest, char *device, size_t device_size);
|
||||||
|
void deviceid_decode_mice (char *comment, char *trimmed, size_t trimmed_size, char *device, size_t device_size);
|
|
@ -129,6 +129,7 @@
|
||||||
#include "dwsock.h"
|
#include "dwsock.h"
|
||||||
#include "dns_sd_dw.h"
|
#include "dns_sd_dw.h"
|
||||||
#include "dlq.h" // for fec_type_t definition.
|
#include "dlq.h" // for fec_type_t definition.
|
||||||
|
#include "deviceid.h"
|
||||||
|
|
||||||
|
|
||||||
//static int idx_decoded = 0;
|
//static int idx_decoded = 0;
|
||||||
|
@ -985,6 +986,7 @@ int main (int argc, char *argv[])
|
||||||
* Files not supported at this time.
|
* Files not supported at this time.
|
||||||
* Can always "cat" the file and pipe it into stdin.
|
* Can always "cat" the file and pipe it into stdin.
|
||||||
*/
|
*/
|
||||||
|
deviceid_init();
|
||||||
|
|
||||||
err = audio_open (&audio_config);
|
err = audio_open (&audio_config);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
|
|
|
@ -147,6 +147,7 @@ list(APPEND dtest_SOURCES
|
||||||
${CUSTOM_SRC_DIR}/tq.c
|
${CUSTOM_SRC_DIR}/tq.c
|
||||||
${CUSTOM_SRC_DIR}/textcolor.c
|
${CUSTOM_SRC_DIR}/textcolor.c
|
||||||
${CUSTOM_SRC_DIR}/decode_aprs.c
|
${CUSTOM_SRC_DIR}/decode_aprs.c
|
||||||
|
${CUSTOM_SRC_DIR}/deviceid.c
|
||||||
${CUSTOM_SRC_DIR}/dwgpsnmea.c
|
${CUSTOM_SRC_DIR}/dwgpsnmea.c
|
||||||
${CUSTOM_SRC_DIR}/dwgps.c
|
${CUSTOM_SRC_DIR}/dwgps.c
|
||||||
${CUSTOM_SRC_DIR}/dwgpsd.c
|
${CUSTOM_SRC_DIR}/dwgpsd.c
|
||||||
|
@ -232,6 +233,7 @@ list(APPEND pftest_SOURCES
|
||||||
${CUSTOM_SRC_DIR}/textcolor.c
|
${CUSTOM_SRC_DIR}/textcolor.c
|
||||||
${CUSTOM_SRC_DIR}/fcs_calc.c
|
${CUSTOM_SRC_DIR}/fcs_calc.c
|
||||||
${CUSTOM_SRC_DIR}/decode_aprs.c
|
${CUSTOM_SRC_DIR}/decode_aprs.c
|
||||||
|
${CUSTOM_SRC_DIR}/deviceid.c
|
||||||
${CUSTOM_SRC_DIR}/dwgpsnmea.c
|
${CUSTOM_SRC_DIR}/dwgpsnmea.c
|
||||||
${CUSTOM_SRC_DIR}/dwgps.c
|
${CUSTOM_SRC_DIR}/dwgps.c
|
||||||
${CUSTOM_SRC_DIR}/dwgpsd.c
|
${CUSTOM_SRC_DIR}/dwgpsd.c
|
||||||
|
@ -522,6 +524,7 @@ if(OPTIONAL_TEST)
|
||||||
${CUSTOM_SRC_DIR}/pfilter.c
|
${CUSTOM_SRC_DIR}/pfilter.c
|
||||||
${CUSTOM_SRC_DIR}/telemetry.c
|
${CUSTOM_SRC_DIR}/telemetry.c
|
||||||
${CUSTOM_SRC_DIR}/decode_aprs.c
|
${CUSTOM_SRC_DIR}/decode_aprs.c
|
||||||
|
${CUSTOM_SRC_DIR}/deviceid.c.c
|
||||||
${CUSTOM_SRC_DIR}/dwgpsnmea.c
|
${CUSTOM_SRC_DIR}/dwgpsnmea.c
|
||||||
${CUSTOM_SRC_DIR}/dwgps.c
|
${CUSTOM_SRC_DIR}/dwgps.c
|
||||||
${CUSTOM_SRC_DIR}/dwgpsd.c
|
${CUSTOM_SRC_DIR}/dwgpsd.c
|
||||||
|
@ -574,6 +577,7 @@ if(OPTIONAL_TEST)
|
||||||
${CUSTOM_SRC_DIR}/fcs_calc.c
|
${CUSTOM_SRC_DIR}/fcs_calc.c
|
||||||
${CUSTOM_SRC_DIR}/ax25_pad.c
|
${CUSTOM_SRC_DIR}/ax25_pad.c
|
||||||
${CUSTOM_SRC_DIR}/decode_aprs.c
|
${CUSTOM_SRC_DIR}/decode_aprs.c
|
||||||
|
${CUSTOM_SRC_DIR}/deviceid.c
|
||||||
${CUSTOM_SRC_DIR}/dwgpsnmea.c
|
${CUSTOM_SRC_DIR}/dwgpsnmea.c
|
||||||
${CUSTOM_SRC_DIR}/dwgps.c
|
${CUSTOM_SRC_DIR}/dwgps.c
|
||||||
${CUSTOM_SRC_DIR}/dwgpsd.c
|
${CUSTOM_SRC_DIR}/dwgpsd.c
|
||||||
|
|
Loading…
Reference in New Issue