summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorScott Miller N1VG <scott@n1vg.net>2004-02-04 22:34:08 +0000
committerScott Miller N1VG <scott@n1vg.net>2004-02-04 22:34:08 +0000
commitc4827aa13af8bd74806ea1e72d91f5862c8c70d6 (patch)
treeeea28f83fdb615f59a229516df3167cccf6f25a6
parentf7c1d9784bc734ef3592f38979567ec08ee06509 (diff)
Minor bug fixes and some restructuring
-rw-r--r--listen/opentracdump.c317
1 files changed, 118 insertions, 199 deletions
diff --git a/listen/opentracdump.c b/listen/opentracdump.c
index 953618b..7a76df2 100644
--- a/listen/opentracdump.c
+++ b/listen/opentracdump.c
@@ -1,6 +1,7 @@
/* OpenTRAC packet decoding by Scott Miller, N1VG
Copyright (c) 2003 Scott Miller
Protocol v1.0 draft, Modified 19 Jun 2003
+ Released under the Modified BSD license
*/
#include <stdio.h>
@@ -11,42 +12,12 @@
#define MAX_UNIT_INDEX 28
const char *units[]={"Volts","Amperes","Watts","Kelvins","Meters","Seconds",
- "Meters/Second","Liters","Kilograms","Bits/Second",
- "Bytes","Radians","Radians/Second","Square Meters",
- "Joules","Newtons","Pascals","Hertz","Meters/Sec^2",
- "Grays","Lumens","Cubic Meters/Second","Pascal Seconds",
- "Kilograms/Meter^3","Radians/Second^2","Coulombs",
+ "Meters/Second","Liters","Kilograms","Bits/Second","Bytes","Radians",
+ "Radians/Second","Square Meters","Joules","Newtons","Pascals","Hertz",
+ "Meters/Sec^2","Grays","Lumens","Cubic Meters/Second",
+ "Pascal Seconds","Kilograms/Meter^3","Radians/Second^2","Coulombs",
"Farads","Siemens","Count"};
-// Return values: 0 = OK, -1 = Couldn't Decode, -2 = Invalid Data
-
-int decode_sequence(unsigned char *element, int element_len);
-int decode_origination(unsigned char *element, int element_len);
-int decode_entityid(unsigned char *element, int element_len);
-int decode_position(unsigned char *element, int element_len);
-int decode_timestamp(unsigned char *element, int element_len);
-int decode_comment(unsigned char *element, int element_len);
-int decode_courseandspeed(unsigned char *element, int element_len);
-int decode_ambiguity(unsigned char *element, int element_len);
-int decode_country(unsigned char *element, int element_len);
-int decode_displayname(unsigned char *element, int element_len);
-int decode_waypoint(unsigned char *element, int element_len);
-int decode_symbol(unsigned char *element, int element_len);
-int decode_pathtrace(unsigned char *element, int element_len);
-int decode_heardby(unsigned char *element, int element_len);
-int decode_availablenets(unsigned char *element, int element_len);
-int decode_maidenhead(unsigned char *element, int element_len);
-int decode_gpsquality(unsigned char *element, int element_len);
-int decode_acreg(unsigned char *element, int element_len);
-int decode_rivergauge(unsigned char *element, int element_len);
-int decode_hazmat(unsigned char *element, int element_len);
-int flag_emergency(void);
-int flag_attention(void);
-
-int extract_ssid(unsigned char *call);
-
-int decode_units(unsigned int unitnum, unsigned char *element, int element_len);
-
unsigned char origin_call[7]; // Who's talking
unsigned char origin_ssid;
unsigned char entity_call[7]; // What they're talking about
@@ -54,110 +25,25 @@ unsigned char entity_ssid;
unsigned int entity_serial;
unsigned int entity_sequence;
-/* Dump an OpenTRAC packet */
-void opentrac_dump(unsigned char *data, int length, int hexdump)
-{
- int elen;
- int etype;
- int decoded = 0;
-
- lprintf(T_PROTOCOL, "OpenTRAC decode (%d bytes):\r\n", length);
- strcpy(origin_call, "SENDER"); // Listen doesn't tell us the sender
- origin_ssid = 0;
- entity_serial = 0;
- entity_sequence = 0;
- while (decoded < length) {
- elen = (int)*data;
- decoded += (elen & 0x7f)+1;
- if (elen & 0x80) { // See if it's got a 16-bit ID
- elen = (elen & 0x7f) - 2; // Strip the extid flag
- etype = get16(++data);
- }
- else {
- elen--; // Don't count the type byte
- etype = (int)*(data+1);
- }
- data+=2; // Skip to the body
- lprintf(T_OPENTRAC, "EID 0x%0x len %d: ", etype, elen);
- switch (etype) {
- case (0x00): // Sequence
- decode_sequence(data, elen);
- break;
- case (0x01): // Originating Station
- decode_origination(data, elen);
- break;
- case (0x02): // Entity ID
- decode_entityid(data, elen);
- break;
- case (0x10): // Position report
- decode_position(data, elen);
- break;
- case (0x11): // Timestamp
- decode_timestamp(data, elen);
- break;
- case (0x12): // Comment
- decode_comment(data, elen);
- break;
- case (0x13): // Course and Speed
- decode_courseandspeed(data, elen);
- break;
- case (0x14): // Positional Ambiguity
- decode_ambiguity(data, elen);
- break;
- case (0x15): // Country Code
- decode_country(data, elen);
- break;
- case (0x16): // Display Name
- decode_displayname(data, elen);
- break;
- case (0x17): // Waypoint Name
- decode_waypoint(data, elen);
- break;
- case (0x18): // Map Symbol
- decode_symbol(data, elen);
- break;
- case (0x20): // Path Trace
- decode_pathtrace(data, elen);
- break;
- case (0x21): // Heard-By List
- decode_heardby(data, elen);
- break;
- case (0x22): // Available Networks
- decode_availablenets(data, elen);
- break;
- case (0x32): // Maidenhead Locator
- decode_maidenhead(data, elen);
- break;
- case (0x34): // GPS Data Quality
- decode_gpsquality(data, elen);
- break;
- case (0x35): // Aircraft Registration
- decode_acreg(data, elen);
- break;
- case (0x42): // River Flow Gauge
- decode_rivergauge(data, elen);
- break;
- case (0x100): // Emergency/distress flag
- flag_emergency();
- break;
- case (0x101): // Attention/ident flag
- flag_attention();
- break;
- case (0x300): // Hazmat
- decode_hazmat(data, elen);
- break;
- default: // Everything else
- if ((etype & 0xff00) == 0x500) {
- decode_units(etype & 0x00ff, data, elen);
- }
- else {
- lprintf(T_OPENTRAC, "Unknown Element Type\r\n");
- }
- }
- data+=elen;
- }
+
+
+int extract_ssid(unsigned char *call) {
+ // Strip the SSID from the callsign and return it
+ int c, ssid;
+
+ for (c=ssid=0;c<6;c++) {
+ ssid |= (call[c] & 0x80) >> (c+2);
+ call[c] &= 0x7f;
+ }
+
+ return ssid;
}
+int decode_units(unsigned int unitnum, unsigned char *element, int element_len);
+
+
+// Return values: 0 = OK, -1 = Couldn't Decode, -2 = Invalid Data
+
int decode_sequence(unsigned char *element, int element_len) {
// 0x00 Sequence number - 16 bit integer
if (element_len != 2 && element_len != 0) return -1;
@@ -175,33 +61,22 @@ int decode_sequence(unsigned char *element, int element_len) {
}
int decode_origination(unsigned char *element, int element_len) {
- // 0x01 Originating Station - Callsign, SSID, Sequence, and Network
- unsigned char network;
-
- if (element_len < 8) return -1;
- if (element_len > 9) return -1;
-
+ // 0x01 Originating Station - Callsign, SSID, and Sequence
memcpy(origin_call, element, 6);
origin_call[6]=0;
origin_ssid = extract_ssid(origin_call);
- entity_sequence = get16(element+6);
+ if (element_len == 8) entity_sequence = get16(element+6);
+ else entity_sequence = 0;
strcpy(entity_call, origin_call);
entity_ssid = origin_ssid;
entity_serial = 0;
- if (element_len == 9) {
- network = *(element+9);
- lprintf(T_OPENTRAC, "Origin: %s-%d seq %d net %d\r\n",origin_call,origin_ssid,entity_sequence,network);
- }
- else lprintf(T_OPENTRAC, "Origin: %s-%d seq %d direct\r\n",origin_call,origin_ssid,entity_sequence);
+ lprintf(T_OPENTRAC, "Origin: %s-%d seq %d\r\n",origin_call,origin_ssid,entity_sequence);
return 0;
}
int decode_entityid(unsigned char *element, int element_len) {
// 0x02 Entity ID
-
- if (element_len > 10) return -1;
-
if (element_len > 5) {
memcpy(entity_call, element, 6);
entity_call[6]=0;
@@ -251,17 +126,18 @@ int decode_position(unsigned char *element, int element_len) {
double lat, lon;
float alt = 0;
- if (element_len < 8) return -1; // Too short!
- if (element_len > 11) return -1; // Too long!
-
lat = get32(element) / semicircles;
lon = get32(element+4) / semicircles;
+ if (lat >= 90 || lat <= -90 || lon >= 180 || lon <= -180) return -2;
if (element_len == 11) {
- alt = ((((*(element+8))<<16)+get16(element+9))/100)-10000;
+ alt = ((*(element+8))<<16)+get16(element+9);
+ alt = (alt/100)-10000;
+ lprintf(T_OPENTRAC, "Position: Lat %f Lon %f Alt %f meters\r\n",
+ lat,lon,alt);
+ }
+ else {
+ lprintf(T_OPENTRAC, "Position: Lat %f Lon %f\r\n",lat,lon);
}
- if (lat >= 90 || lat <= -90 || lon >= 180 || lon <= -180) return -2;
- lprintf(T_OPENTRAC, "Position: Lat %f Lon %f Alt %f\r\n",lat,lon,alt);
-
return 0;
}
@@ -269,11 +145,8 @@ int decode_timestamp(unsigned char *element, int element_len) {
// 0x11 Timestamp - Unix format time (unsigned)
long rawtime = 0;
- if (element_len != 4) return -1;
-
rawtime = get32(element);
lprintf(T_OPENTRAC, "Time: %s", ctime(&rawtime));
-
return 0;
}
@@ -281,8 +154,6 @@ int decode_comment(unsigned char *element, int element_len) {
// 0x12 Freeform Comment - ASCII text
char comment[127];
- if (element_len > 126) return -1; // shouldn't be possible
-
strncpy(comment, element, element_len);
comment[element_len] = 0;
lprintf(T_OPENTRAC, "Text: %s\r\n", comment);
@@ -296,10 +167,8 @@ int decode_courseandspeed(unsigned char *element, int element_len) {
unsigned int rawspeed;
float speed;
- if (element_len != 3) return -1;
-
- course = (*element<<1) + ((*(element+1)&0x8000) >> 15);
- rawspeed = (get16(element+1) & 0x7ffff);
+ course = (*element<<1) | ((*(element+1)&0x80) >> 7);
+ rawspeed = get16(element+1) & 0x7fff;
speed = (float)rawspeed*0.072; // kph
if (course >= 360) return -2;
lprintf(T_OPENTRAC, "Course: %d Speed: %f kph\r\n", course, speed);
@@ -311,8 +180,6 @@ int decode_ambiguity(unsigned char *element, int element_len) {
// 0x14 Positional Ambiguity - 16 bits, in meters
int ambiguity;
- if (element_len != 2) return -1;
-
ambiguity = get16(element);
lprintf(T_OPENTRAC, "Position +/- %d meters\r\n", ambiguity);
return 0;
@@ -323,9 +190,6 @@ int decode_country(unsigned char *element, int element_len) {
char country[3];
char subdivision[4];
- if (element_len < 2) return -1;
- if (element_len > 5) return -1;
-
strncpy(country, element, 2);
country[2] = 0;
if (element_len > 2) {
@@ -343,8 +207,6 @@ int decode_displayname(unsigned char *element, int element_len) {
// 0x16 - Display Name (UTF-8 text)
char displayname[31];
- if (element_len > 30 || !element_len) return -1;
-
strncpy(displayname, element, element_len);
displayname[element_len] = 0;
@@ -356,8 +218,6 @@ int decode_waypoint(unsigned char *element, int element_len) {
// 0x17 - Waypoint Name (up to 6 chars, uppercase)
char waypoint[7];
- if (element_len > 6 || !element_len) return -1;
-
strncpy(waypoint, element, element_len);
waypoint[element_len] = 0;
@@ -369,8 +229,6 @@ int decode_symbol(unsigned char *element, int element_len) {
// 0x18 Map Symbol - Packed 4-bit integers
int c;
- if (!element_len) return -1;
-
lprintf(T_OPENTRAC, "Symbol: ");
for (c=0;c<element_len;c++) {
if (c>0) lprintf(T_OPENTRAC, ".");
@@ -438,17 +296,15 @@ int decode_gpsquality(unsigned char *element, int element_len) {
const char *validstr[] = {"Invalid", "Valid SPS", "Valid DGPS",
"Valid PPS"};
- if (element_len > 4 || !element_len) return -1;
-
fixtype = (element[0] & 0xc0) >> 6;
validity = (element[0] & 0x30) >> 4;
sats = (element[0] & 0x0f);
lprintf(T_OPENTRAC, "GPS: %s %s, %d sats", fixstr[fixtype],
validstr[validity], sats);
if (element_len > 1)
- lprintf(T_OPENTRAC, " PDOP=%.1f", (float)element[1]/10);
+ lprintf(T_OPENTRAC, " HDOP=%.1f", (float)element[1]/10);
if (element_len > 2)
- lprintf(T_OPENTRAC, " HDOP=%.1f", (float)element[2]/10);
+ lprintf(T_OPENTRAC, " PDOP=%.1f", (float)element[2]/10);
if (element_len > 3)
lprintf(T_OPENTRAC, " VDOP=%.1f", (float)element[3]/10);
lprintf(T_OPENTRAC, "\r\n");
@@ -461,8 +317,6 @@ int decode_acreg(unsigned char *element, int element_len) {
// 0x35 Aircraft Registration - ASCII text
char nnumber[9];
- if (element_len > 8) return -1;
-
strncpy(nnumber, element, element_len);
nnumber[element_len]=0;
lprintf(T_OPENTRAC, "Aircraft ID: %s\r\n", nnumber);
@@ -477,8 +331,6 @@ int decode_rivergauge(unsigned char *element, int element_len) {
float flowm;
float heightm;
- if (element_len != 4) return -1;
-
flow = get16(element);
height = get16(element+2);
flowm = (float)flow / 64;
@@ -523,13 +375,13 @@ int decode_units(unsigned int unitnum, unsigned char *element, int element_len)
return 0;
}
-int flag_emergency(void) {
+int flag_emergency(unsigned char *element, int element_len) {
// 0x0100 - Emergency / Distress Call
lprintf(T_ERROR, "* * * EMERGENCY * * *\r\n");
return 0;
}
-int flag_attention(void) {
+int flag_attention(unsigned char *element, int element_len) {
// 0x0101 - Attention / Ident
lprintf(T_PROTOCOL, " - ATTENTION - \r\n");
return 0;
@@ -542,8 +394,7 @@ int decode_hazmat(unsigned char *element, int element_len) {
if (element_len < 2) {
lprintf(T_OPENTRAC, "HAZMAT: Unknown Material\r\n");
}
- else
- {
+ else {
un_id = get16(element) & 0x3fff;
lprintf(T_OPENTRAC, "HAZMAT: UN%04d\r\n", un_id);
}
@@ -563,15 +414,83 @@ int decode_maidenhead(unsigned char *element, int element_len) {
return 0;
}
-int extract_ssid(unsigned char *call) {
- // Strip the SSID from the callsign and return it
- int c, ssid;
- for (c=ssid=0;c<6;c++) {
- ssid |= (call[c] & 0x80) >> (c+2);
- call[c] &= 0x7f;
- }
+struct {
+ unsigned int element_id;
+ unsigned char min_size;
+ unsigned char max_size;
+ int (*pDecode)(unsigned char *element, int element_len);
+} element_decode[] = {{0x00, 0, 2, decode_sequence},
+ {0x01, 6, 8, decode_origination},
+ {0x02, 0, 10, decode_entityid},
+ {0x10, 8, 11, decode_position},
+ {0x11, 4, 4, decode_timestamp},
+ {0x12, 0, 127, decode_comment},
+ {0x13, 3, 3, decode_courseandspeed},
+ {0x14, 2, 2, decode_ambiguity},
+ {0x15, 2, 5, decode_country},
+ {0x16, 1, 30, decode_displayname},
+ {0x17, 1, 6, decode_waypoint},
+ {0x18, 1, 4, decode_symbol},
+ {0x20, 0, 127, decode_pathtrace},
+ {0x21, 0, 127, decode_heardby},
+ {0x22, 0, 127, decode_availablenets},
+ {0x32, 4, 6, decode_maidenhead},
+ {0x34, 1, 4, decode_gpsquality},
+ {0x35, 1, 8, decode_acreg},
+ {0x42, 4, 4, decode_rivergauge},
+ {0x100, 0, 127, flag_emergency},
+ {0x101, 0, 127, flag_attention},
+ {0x300, 0, 2, decode_hazmat},
+ {0, 0, 0, NULL}}, *element_decode_ptr;
- return ssid;
-}
+/* Dump an OpenTRAC packet */
+void opentrac_dump(unsigned char *data, int length, int hexdump)
+{
+ int elen;
+ int etype;
+ int decoded = 0;
+
+ lprintf(T_PROTOCOL, "OpenTRAC decode (%d bytes):\r\n", length);
+ strcpy(origin_call, "SENDER"); // Listen doesn't tell us the sender
+ origin_ssid = 0;
+ entity_serial = 0;
+ entity_sequence = 0;
+ while (decoded < length) {
+ elen = (int)*data;
+ decoded += (elen & 0x7f)+1;
+ if (elen & 0x80) { // See if it's got a 16-bit ID
+ elen = (elen & 0x7f) - 2; // Strip the extid flag
+ etype = get16(++data);
+ }
+ else {
+ elen--; // Don't count the type byte
+ etype = (int)*(data+1);
+ }
+ data+=2; // Skip to the body
+ lprintf(T_OPENTRAC, "EID 0x%0x len %d: ", etype, elen);
+ for (element_decode_ptr = element_decode; element_decode_ptr->pDecode != NULL; element_decode_ptr++) {
+ if (etype == element_decode_ptr->element_id) {
+ if (elen < element_decode_ptr->min_size || elen > element_decode_ptr->max_size) {
+ lprintf(T_OPENTRAC, "Invalid element length\r\n");
+ }
+ else {
+ if (element_decode_ptr->pDecode(data, elen)) {
+ lprintf(T_OPENTRAC, "Unable to decode\r\n");
+ }
+ }
+ break;
+ }
+ }
+ if (element_decode_ptr->pDecode == NULL) {
+ if ((etype & 0xff00) == 0x500) {
+ decode_units(etype & 0x00ff, data, elen);
+ }
+ else {
+ lprintf(T_OPENTRAC, "Unknown element type - unable to decode.\r\n");
+ }
+ }
+ data+=elen;
+ }
+}