diff --git a/adsbus/adsb.pb-c.c b/adsbus/adsb.pb-c.c index 8381d08..3b3e1fe 100644 --- a/adsbus/adsb.pb-c.c +++ b/adsbus/adsb.pb-c.c @@ -359,7 +359,7 @@ const ProtobufCMessageDescriptor adsb_packet__descriptor = (ProtobufCMessageInit) adsb_packet__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor adsb__field_descriptors[3] = +static const ProtobufCFieldDescriptor adsb__field_descriptors[4] = { { "header", @@ -374,11 +374,23 @@ static const ProtobufCFieldDescriptor adsb__field_descriptors[3] = 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "mode_s_short", + "mode_ac", 2, PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ + offsetof(Adsb, mode_ac), + &adsb_packet__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "mode_s_short", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ offsetof(Adsb, mode_s_short), &adsb_packet__descriptor, NULL, @@ -387,7 +399,7 @@ static const ProtobufCFieldDescriptor adsb__field_descriptors[3] = }, { "mode_s_long", - 3, + 4, PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ @@ -400,13 +412,14 @@ static const ProtobufCFieldDescriptor adsb__field_descriptors[3] = }; static const unsigned adsb__field_indices_by_name[] = { 0, /* field[0] = header */ - 2, /* field[2] = mode_s_long */ - 1, /* field[1] = mode_s_short */ + 1, /* field[1] = mode_ac */ + 3, /* field[3] = mode_s_long */ + 2, /* field[2] = mode_s_short */ }; static const ProtobufCIntRange adsb__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 3 } + { 0, 4 } }; const ProtobufCMessageDescriptor adsb__descriptor = { @@ -416,7 +429,7 @@ const ProtobufCMessageDescriptor adsb__descriptor = "Adsb", "", sizeof(Adsb), - 3, + 4, adsb__field_descriptors, adsb__field_indices_by_name, 1, adsb__number_ranges, diff --git a/adsbus/adsb.pb-c.h b/adsbus/adsb.pb-c.h index 298b82c..5905a30 100644 --- a/adsbus/adsb.pb-c.h +++ b/adsbus/adsb.pb-c.h @@ -60,12 +60,13 @@ struct _Adsb { ProtobufCMessage base; AdsbHeader *header; + AdsbPacket *mode_ac; AdsbPacket *mode_s_short; AdsbPacket *mode_s_long; }; #define ADSB__INIT \ { PROTOBUF_C_MESSAGE_INIT (&adsb__descriptor) \ - , NULL, NULL, NULL } + , NULL, NULL, NULL, NULL } struct _AdsbStream diff --git a/adsbus/airspy_adsb.c b/adsbus/airspy_adsb.c index c177905..be1a020 100644 --- a/adsbus/airspy_adsb.c +++ b/adsbus/airspy_adsb.c @@ -12,29 +12,14 @@ #define SEND_MHZ 20 -struct __attribute__((packed)) airspy_adsb_common_overlay { - uint8_t mlat_timestamp[8]; +struct __attribute__((packed)) airspy_adsb_overlay { char semicolon1; - uint8_t mlat_precision[2]; + uint8_t mlat_timestamp[8]; char semicolon2; - uint8_t rssi[4]; + uint8_t mlat_precision[2]; char semicolon3; -}; - -struct __attribute__((packed)) airspy_adsb_mode_s_short_overlay { - char asterisk; - uint8_t payload[14]; - char semicolon; - struct airspy_adsb_common_overlay common; - char cr_lf; - char lf; -}; - -struct __attribute__((packed)) airspy_adsb_mode_s_long_overlay { - char asterisk; - uint8_t payload[28]; - char semicolon; - struct airspy_adsb_common_overlay common; + uint8_t rssi[4]; + char semicolon4; char cr_lf; char lf; }; @@ -43,10 +28,19 @@ struct airspy_adsb_parser_state { struct packet_mlat_state mlat_state; }; -static bool airspy_adsb_parse_common(const struct airspy_adsb_common_overlay *overlay, struct packet *packet, struct airspy_adsb_parser_state *state) { - if (overlay->semicolon1 != ';' || +static bool airspy_adsb_parse_packet(struct buf *buf, struct packet *packet, struct airspy_adsb_parser_state *state, enum packet_type type) { + size_t payload_bytes = packet_payload_len[type]; + size_t overlay_start = 1 + payload_bytes; + struct airspy_adsb_overlay *overlay = (struct airspy_adsb_overlay *) buf_at(buf, overlay_start); + size_t total_len = overlay_start + sizeof(*overlay); + + if (((buf->length < total_len - 1 || overlay->cr_lf != '\n') && + (buf->length < total_len || overlay->cr_lf != '\r' || overlay->lf != '\n')) || + buf_chr(buf, 0) != '*' || + overlay->semicolon1 != ';' || overlay->semicolon2 != ';' || - overlay->semicolon3 != ';') { + overlay->semicolon3 != ';' || + overlay->semicolon4 != ';') { return false; } uint16_t mlat_mhz = 2 * (uint16_t) hex_to_int(overlay->mlat_precision, sizeof(overlay->mlat_precision) / 2); @@ -59,108 +53,41 @@ static bool airspy_adsb_parse_common(const struct airspy_adsb_common_overlay *ov } packet->mlat_timestamp = packet_mlat_timestamp_scale_in((uint64_t) mlat_timestamp_in, UINT32_MAX, mlat_mhz, &state->mlat_state); packet->rssi = packet_rssi_scale_in((uint32_t) hex_to_int(overlay->rssi, sizeof(overlay->rssi) / 2), UINT16_MAX); + packet->type = type; + if (!hex_to_bin(packet->payload, buf_at(buf, 1), payload_bytes)) { + return false; + } + buf_consume(buf, overlay->cr_lf == '\r' ? total_len : total_len - 1); return true; } -static bool airspy_adsb_parse_mode_s_short(struct buf *buf, struct packet *packet, struct airspy_adsb_parser_state *state) { - struct airspy_adsb_mode_s_short_overlay *overlay = (struct airspy_adsb_mode_s_short_overlay *) buf_at(buf, 0); - if (((buf->length < sizeof(*overlay) - 1 || overlay->cr_lf != '\n') && - (buf->length < sizeof(*overlay) || overlay->cr_lf != '\r' || overlay->lf != '\n')) || - overlay->asterisk != '*' || - overlay->semicolon != ';') { - return false; - } - if (!airspy_adsb_parse_common(&overlay->common, packet, state)) { - return false; - } - packet->type = PACKET_TYPE_MODE_S_SHORT; - if (!hex_to_bin(packet->payload, overlay->payload, sizeof(overlay->payload) / 2)) { - return false; - } - buf_consume(buf, overlay->cr_lf == '\r' ? sizeof(*overlay) : sizeof(*overlay) - 1); - return true; -} - -static bool airspy_adsb_parse_mode_s_long(struct buf *buf, struct packet *packet, struct airspy_adsb_parser_state *state) { - struct airspy_adsb_mode_s_long_overlay *overlay = (struct airspy_adsb_mode_s_long_overlay *) buf_at(buf, 0); - if (((buf->length < sizeof(*overlay) - 1 || overlay->cr_lf != '\n') && - (buf->length < sizeof(*overlay) || overlay->cr_lf != '\r' || overlay->lf != '\n')) || - overlay->asterisk != '*' || - overlay->semicolon != ';') { - return false; - } - if (!airspy_adsb_parse_common(&overlay->common, packet, state)) { - return false; - } - packet->type = PACKET_TYPE_MODE_S_LONG; - if (!hex_to_bin(packet->payload, overlay->payload, sizeof(overlay->payload) / 2)) { - return false; - } - buf_consume(buf, overlay->cr_lf == '\r' ? sizeof(*overlay) : sizeof(*overlay) - 1); - return true; -} - -static void airspy_adsb_fill_common(struct packet *packet, struct airspy_adsb_common_overlay *overlay) { - overlay->semicolon1 = overlay->semicolon2 = overlay->semicolon3 = ';'; - hex_from_int_upper( - overlay->mlat_timestamp, - packet_mlat_timestamp_scale_out(packet->mlat_timestamp, UINT32_MAX, SEND_MHZ), - sizeof(overlay->mlat_timestamp) / 2); - hex_from_int_upper(overlay->mlat_precision, SEND_MHZ / 2, sizeof(overlay->mlat_precision) / 2); - hex_from_int_upper(overlay->rssi, packet_rssi_scale_out(packet->rssi, UINT16_MAX), sizeof(overlay->rssi) / 2); -} - -static void airspy_adsb_serialize_mode_s_short(struct packet *packet, struct buf *buf) { - struct airspy_adsb_mode_s_short_overlay *overlay = (struct airspy_adsb_mode_s_short_overlay *) buf_at(buf, 0); - overlay->asterisk = '*'; - overlay->semicolon = ';'; - overlay->cr_lf = '\r'; - overlay->lf = '\n'; - hex_from_bin_upper(overlay->payload, packet->payload, sizeof(overlay->payload) / 2); - - airspy_adsb_fill_common(packet, &overlay->common); - - buf->length = sizeof(*overlay); -} - -static void airspy_adsb_serialize_mode_s_long(struct packet *packet, struct buf *buf) { - struct airspy_adsb_mode_s_long_overlay *overlay = (struct airspy_adsb_mode_s_long_overlay *) buf_at(buf, 0); - overlay->asterisk = '*'; - overlay->semicolon = ';'; - overlay->cr_lf = '\r'; - overlay->lf = '\n'; - hex_from_bin_upper(overlay->payload, packet->payload, sizeof(overlay->payload) / 2); - - airspy_adsb_fill_common(packet, &overlay->common); - - buf->length = sizeof(*overlay); -} - void airspy_adsb_init() { assert(sizeof(struct airspy_adsb_parser_state) <= PARSER_STATE_LEN); - assert(sizeof(struct airspy_adsb_mode_s_short_overlay) < BUF_LEN_MAX); - assert(sizeof(struct airspy_adsb_mode_s_long_overlay) < BUF_LEN_MAX); + assert(1 + PACKET_PAYLOAD_LEN_MAX + sizeof(struct airspy_adsb_overlay) < BUF_LEN_MAX); } bool airspy_adsb_parse(struct buf *buf, struct packet *packet, void *state_in) { struct airspy_adsb_parser_state *state = (struct airspy_adsb_parser_state *) state_in; return ( - airspy_adsb_parse_mode_s_short(buf, packet, state) || - airspy_adsb_parse_mode_s_long(buf, packet, state)); + airspy_adsb_parse_packet(buf, packet, state, PACKET_TYPE_MODE_AC) || + airspy_adsb_parse_packet(buf, packet, state, PACKET_TYPE_MODE_S_SHORT) || + airspy_adsb_parse_packet(buf, packet, state, PACKET_TYPE_MODE_S_LONG)); } void airspy_adsb_serialize(struct packet *packet, struct buf *buf) { - switch (packet->type) { - case PACKET_TYPE_NONE: - break; - - case PACKET_TYPE_MODE_S_SHORT: - airspy_adsb_serialize_mode_s_short(packet, buf); - break; - - case PACKET_TYPE_MODE_S_LONG: - airspy_adsb_serialize_mode_s_long(packet, buf); - break; - } + size_t payload_bytes = packet_payload_len[packet->type]; + struct airspy_adsb_overlay *overlay = (struct airspy_adsb_overlay *) buf_at(buf, 1 + payload_bytes); + buf_chr(buf, 0) = '*'; + overlay->semicolon1 = overlay->semicolon2 = overlay->semicolon3 = overlay->semicolon4 =';'; + overlay->cr_lf = '\r'; + overlay->lf = '\n'; + hex_from_bin_upper(buf_at(buf, 1), packet->payload, payload_bytes); + hex_from_int_upper( + overlay->mlat_timestamp, + packet_mlat_timestamp_scale_out(packet->mlat_timestamp, UINT32_MAX, SEND_MHZ), + sizeof(overlay->mlat_timestamp) / 2); + hex_from_int_upper(overlay->mlat_precision, SEND_MHZ / 2, sizeof(overlay->mlat_precision) / 2); + hex_from_int_upper(overlay->rssi, packet_rssi_scale_out(packet->rssi, UINT16_MAX), sizeof(overlay->rssi) / 2); + buf->length = 1 + payload_bytes + sizeof(*overlay); } diff --git a/adsbus/beast.c b/adsbus/beast.c index ab409b8..020b9f2 100644 --- a/adsbus/beast.c +++ b/adsbus/beast.c @@ -9,29 +9,19 @@ #include "beast.h" -struct __attribute__((packed)) beast_common_overlay { +struct __attribute__((packed)) beast_overlay { uint8_t one_a; uint8_t type; -}; - -struct __attribute__((packed)) beast_mode_s_short_overlay { - struct beast_common_overlay common; uint8_t mlat_timestamp[6]; uint8_t rssi; - uint8_t payload[7]; -}; - -struct __attribute__((packed)) beast_mode_s_long_overlay { - struct beast_common_overlay common; - uint8_t mlat_timestamp[6]; - uint8_t rssi; - uint8_t payload[14]; }; struct beast_parser_state { struct packet_mlat_state mlat_state; }; +#define BEAST_MLAT_MHZ 12 + static uint64_t beast_parse_mlat(uint8_t *mlat_timestamp) { return ( ((uint64_t) mlat_timestamp[0]) << 40 | @@ -78,46 +68,32 @@ static void beast_escape(struct buf *out, const struct buf *in) { } } -static bool beast_parse_mode_s_short(struct buf *buf, struct packet *packet, struct beast_parser_state *state) { +static bool beast_parse_packet(struct buf *buf, struct packet *packet, struct beast_parser_state *state, enum packet_type type) { struct buf buf2 = BUF_INIT; - ssize_t in_bytes = beast_unescape(&buf2, buf, sizeof(struct beast_mode_s_short_overlay)); + size_t payload_bytes = packet_payload_len[type]; + ssize_t in_bytes = beast_unescape(&buf2, buf, sizeof(struct beast_overlay) + payload_bytes); if (in_bytes < 0) { return false; } - struct beast_mode_s_short_overlay *overlay = (struct beast_mode_s_short_overlay *) buf_at(&buf2, 0); - packet->type = PACKET_TYPE_MODE_S_SHORT; + struct beast_overlay *overlay = (struct beast_overlay *) buf_at(&buf2, 0); + packet->type = type; uint64_t source_mlat = beast_parse_mlat(overlay->mlat_timestamp); - packet->mlat_timestamp = packet_mlat_timestamp_scale_in(source_mlat, UINT64_C(0xffffffffffff), 12, &state->mlat_state); + packet->mlat_timestamp = packet_mlat_timestamp_scale_in(source_mlat, UINT64_C(0xffffffffffff), BEAST_MLAT_MHZ, &state->mlat_state); packet->rssi = packet_rssi_scale_in(overlay->rssi, UINT8_MAX); - memcpy(packet->payload, overlay->payload, sizeof(overlay->payload)); + memcpy(packet->payload, buf_at(&buf2, sizeof(*overlay)), payload_bytes); buf_consume(buf, (size_t) in_bytes); return true; } -static bool beast_parse_mode_s_long(struct buf *buf, struct packet *packet, struct beast_parser_state *state) { +static void beast_serialize_packet(struct packet *packet, struct buf *buf, uint8_t type) { struct buf buf2 = BUF_INIT; - ssize_t in_bytes = beast_unescape(&buf2, buf, sizeof(struct beast_mode_s_long_overlay)); - if (in_bytes < 0) { - return false; - } - struct beast_mode_s_long_overlay *overlay = (struct beast_mode_s_long_overlay *) buf_at(&buf2, 0); - packet->type = PACKET_TYPE_MODE_S_LONG; - uint64_t source_mlat = beast_parse_mlat(overlay->mlat_timestamp); - packet->mlat_timestamp = packet_mlat_timestamp_scale_in(source_mlat, UINT64_C(0xffffffffffff), 12, &state->mlat_state); - packet->rssi = packet_rssi_scale_in(overlay->rssi == UINT8_MAX ? 0 : overlay->rssi, UINT8_MAX); - memcpy(packet->payload, overlay->payload, sizeof(overlay->payload)); - buf_consume(buf, (size_t) in_bytes); - return true; -} - -static void beast_serialize_mode_s_short(struct packet *packet, struct buf *buf) { - struct buf buf2 = BUF_INIT; - struct beast_mode_s_short_overlay *overlay = (struct beast_mode_s_short_overlay *) buf_at(&buf2, 0); - overlay->common.one_a = 0x1a; - overlay->common.type = 0x32; - memcpy(overlay->payload, packet->payload, sizeof(overlay->payload)); + size_t payload_bytes = packet_payload_len[type]; + struct beast_overlay *overlay = (struct beast_overlay *) buf_at(&buf2, 0); + overlay->one_a = 0x1a; + overlay->type = type; + memcpy(buf_at(&buf2, sizeof(*overlay)), packet->payload, payload_bytes); beast_write_mlat( - packet_mlat_timestamp_scale_out(packet->mlat_timestamp, UINT64_C(0xffffffffffff), 12), + packet_mlat_timestamp_scale_out(packet->mlat_timestamp, UINT64_C(0xffffffffffff), BEAST_MLAT_MHZ), overlay->mlat_timestamp); if (packet->rssi) { @@ -126,54 +102,35 @@ static void beast_serialize_mode_s_short(struct packet *packet, struct buf *buf) overlay->rssi = UINT8_MAX; } - buf2.length = sizeof(*overlay); - beast_escape(buf, &buf2); -} - -static void beast_serialize_mode_s_long(struct packet *packet, struct buf *buf) { - struct buf buf2 = BUF_INIT; - struct beast_mode_s_long_overlay *overlay = (struct beast_mode_s_long_overlay *) buf_at(&buf2, 0); - overlay->common.one_a = 0x1a; - overlay->common.type = 0x33; - memcpy(overlay->payload, packet->payload, sizeof(overlay->payload)); - beast_write_mlat( - packet_mlat_timestamp_scale_out(packet->mlat_timestamp, UINT64_C(0xffffffffffff), 12), - overlay->mlat_timestamp); - - if (packet->rssi) { - overlay->rssi = (uint8_t) packet_rssi_scale_out(packet->rssi, UINT8_MAX); - } else { - overlay->rssi = UINT8_MAX; - } - - buf2.length = sizeof(*overlay); + buf2.length = sizeof(*overlay) + payload_bytes; beast_escape(buf, &buf2); } void beast_init() { assert(sizeof(struct beast_parser_state) <= PARSER_STATE_LEN); - assert(sizeof(struct beast_mode_s_short_overlay) * 2 <= BUF_LEN_MAX); - assert(sizeof(struct beast_mode_s_long_overlay) * 2 <= BUF_LEN_MAX); + assert((sizeof(struct beast_overlay) + PACKET_PAYLOAD_LEN_MAX) * 2 <= BUF_LEN_MAX); } bool beast_parse(struct buf *buf, struct packet *packet, void *state_in) { struct beast_parser_state *state = (struct beast_parser_state *) state_in; + struct beast_overlay *overlay = (struct beast_overlay *) buf_at(buf, 0); - if (buf->length < sizeof(struct beast_common_overlay) || + if (buf->length < sizeof(*overlay) || buf_chr(buf, 0) != 0x1a) { return false; } - struct beast_common_overlay *overlay = (struct beast_common_overlay *) buf_at(buf, 0); switch (overlay->type) { + case 0x31: + return beast_parse_packet(buf, packet, state, PACKET_TYPE_MODE_AC); + case 0x32: - return beast_parse_mode_s_short(buf, packet, state); + return beast_parse_packet(buf, packet, state, PACKET_TYPE_MODE_S_SHORT); case 0x33: - return beast_parse_mode_s_long(buf, packet, state); + return beast_parse_packet(buf, packet, state, PACKET_TYPE_MODE_S_LONG); default: - fprintf(stderr, "R %s: Unknown beast type %x\n", packet->source_id, overlay->type); return false; } return false; @@ -184,12 +141,16 @@ void beast_serialize(struct packet *packet, struct buf *buf) { case PACKET_TYPE_NONE: break; + case PACKET_TYPE_MODE_AC: + beast_serialize_packet(packet, buf, 0x31); + break; + case PACKET_TYPE_MODE_S_SHORT: - beast_serialize_mode_s_short(packet, buf); + beast_serialize_packet(packet, buf, 0x32); break; case PACKET_TYPE_MODE_S_LONG: - beast_serialize_mode_s_long(packet, buf); + beast_serialize_packet(packet, buf, 0x33); break; } } diff --git a/adsbus/json.c b/adsbus/json.c index e5c2e4d..2be7030 100644 --- a/adsbus/json.c +++ b/adsbus/json.c @@ -44,18 +44,11 @@ static void json_add_common(struct packet *packet, json_t *obj) { } } -static void json_serialize_mode_s_short(struct packet *packet, struct buf *buf) { - uint8_t hexbuf[14]; - hex_from_bin_upper(hexbuf, packet->payload, 7); - json_t *out = json_pack("{ss#}", "payload", hexbuf, 14); - json_add_common(packet, out); - json_serialize_to_buf(out, buf); -} - -static void json_serialize_mode_s_long(struct packet *packet, struct buf *buf) { - uint8_t hexbuf[28]; - hex_from_bin_upper(hexbuf, packet->payload, 14); - json_t *out = json_pack("{ss#}", "payload", hexbuf, 28); +static void json_serialize_payload(struct packet *packet, struct buf *buf) { + size_t bytes = packet_payload_len[packet->type]; + uint8_t hexbuf[PACKET_PAYLOAD_LEN_MAX * 2]; + hex_from_bin_upper(hexbuf, packet->payload, bytes); + json_t *out = json_pack("{ss#}", "payload", hexbuf, bytes * 2); json_add_common(packet, out); json_serialize_to_buf(out, buf); } @@ -139,38 +132,34 @@ static bool json_parse_common(json_t *in, struct packet *packet, struct json_par return true; } -static bool json_parse_mode_s_short(json_t *in, struct packet *packet, struct json_parser_state *state) { +static bool json_parse_payload(json_t *in, struct packet *packet, struct json_parser_state *state, enum packet_type type) { + size_t bytes = packet_payload_len[type]; if (!json_parse_common(in, packet, state)) { return false; } json_t *payload = json_object_get(in, "payload"); - if (!payload || !json_is_string(payload) || json_string_length(payload) != 14) { + if (!payload || !json_is_string(payload) || json_string_length(payload) != bytes * 2) { return false; } - if (!hex_to_bin(packet->payload, (const uint8_t *) json_string_value(payload), 7)) { + if (!hex_to_bin(packet->payload, (const uint8_t *) json_string_value(payload), bytes)) { return false; } - packet->type = PACKET_TYPE_MODE_S_SHORT; + packet->type = type; return true; } +static bool json_parse_mode_ac(json_t *in, struct packet *packet, struct json_parser_state *state) { + return json_parse_payload(in, packet, state, PACKET_TYPE_MODE_AC); +} + +static bool json_parse_mode_s_short(json_t *in, struct packet *packet, struct json_parser_state *state) { + return json_parse_payload(in, packet, state, PACKET_TYPE_MODE_S_SHORT); +} + static bool json_parse_mode_s_long(json_t *in, struct packet *packet, struct json_parser_state *state) { - if (!json_parse_common(in, packet, state)) { - return false; - } - - json_t *payload = json_object_get(in, "payload"); - if (!payload || !json_is_string(payload) || json_string_length(payload) != 28) { - return false; - } - - if (!hex_to_bin(packet->payload, (const uint8_t *) json_string_value(payload), 14)) { - return false; - } - packet->type = PACKET_TYPE_MODE_S_LONG; - return true; + return json_parse_payload(in, packet, state, PACKET_TYPE_MODE_S_LONG); } void json_init() { @@ -226,6 +215,8 @@ bool json_parse(struct buf *buf, struct packet *packet, void *state_in) { bool (*parser)(json_t *, struct packet *, struct json_parser_state *) = NULL; if (!strcmp(type_str, "header")) { parser = json_parse_header; + } else if (!strcmp(type_str, "Mode-AC")) { + parser = json_parse_mode_ac; } else if (!strcmp(type_str, "Mode-S short")) { parser = json_parse_mode_s_short; } else if (!strcmp(type_str, "Mode-S long")) { @@ -251,12 +242,10 @@ void json_serialize(struct packet *packet, struct buf *buf) { case PACKET_TYPE_NONE: break; + case PACKET_TYPE_MODE_AC: case PACKET_TYPE_MODE_S_SHORT: - json_serialize_mode_s_short(packet, buf); - break; - case PACKET_TYPE_MODE_S_LONG: - json_serialize_mode_s_long(packet, buf); + json_serialize_payload(packet, buf); break; } } diff --git a/adsbus/packet.c b/adsbus/packet.c index cd7df3b..6232e81 100644 --- a/adsbus/packet.c +++ b/adsbus/packet.c @@ -1,3 +1,5 @@ +#pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare" + #include #include #include @@ -8,10 +10,18 @@ char *packet_type_names[] = { "INVALID", + "Mode-AC", "Mode-S short", "Mode-S long", }; +size_t packet_payload_len[] = { + 0, + 2, + 7, + 14, +}; + static uint64_t packet_mlat_timestamp_scale_mhz_in(uint64_t timestamp, uint32_t mhz) { assert(mhz > 0); return timestamp * (PACKET_MLAT_MHZ / mhz); diff --git a/adsbus/packet.h b/adsbus/packet.h index ebb5420..66f50f5 100644 --- a/adsbus/packet.h +++ b/adsbus/packet.h @@ -6,17 +6,21 @@ #define PACKET_DATA_LEN_MAX 14 struct packet { const uint8_t *source_id; - enum { + enum packet_type { PACKET_TYPE_NONE, + PACKET_TYPE_MODE_AC, PACKET_TYPE_MODE_S_SHORT, PACKET_TYPE_MODE_S_LONG, } type; - #define NUM_TYPES 3 +#define NUM_TYPES 4 uint8_t payload[PACKET_DATA_LEN_MAX]; uint64_t mlat_timestamp; uint32_t rssi; }; extern char *packet_type_names[]; +extern size_t packet_payload_len[]; + +#define PACKET_PAYLOAD_LEN_MAX 14 #define PACKET_MLAT_MHZ 120 // Use the signed max to avoid problems with some consumers; it's large enough to not matter. diff --git a/adsbus/proto.c b/adsbus/proto.c index 8352fde..35ce4fb 100644 --- a/adsbus/proto.c +++ b/adsbus/proto.c @@ -55,6 +55,14 @@ static void proto_serialize_packet(struct packet *packet, AdsbPacket *out, size_ out->payload.len = len; } +static void proto_serialize_mode_ac(struct packet *packet, struct buf *buf) { + AdsbPacket packet_out = ADSB_PACKET__INIT; + proto_serialize_packet(packet, &packet_out, 2); + Adsb msg = ADSB__INIT; + msg.mode_ac = &packet_out; + proto_wrap_to_buf(&msg, buf); +} + static void proto_serialize_mode_s_short(struct packet *packet, struct buf *buf) { AdsbPacket packet_out = ADSB_PACKET__INIT; proto_serialize_packet(packet, &packet_out, 7); @@ -216,6 +224,12 @@ bool proto_parse(struct buf *buf, struct packet *packet, void *state_in) { return false; } packet->type = PACKET_TYPE_NONE; + } else if (msg->mode_ac) { + if (!proto_parse_packet(msg->mode_ac, packet, state, 2)) { + adsb__free_unpacked(msg, NULL); + return false; + } + packet->type = PACKET_TYPE_MODE_AC; } else if (msg->mode_s_short) { if (!proto_parse_packet(msg->mode_s_short, packet, state, 7)) { adsb__free_unpacked(msg, NULL); @@ -244,6 +258,11 @@ void proto_serialize(struct packet *packet, struct buf *buf) { case PACKET_TYPE_NONE: break; + case PACKET_TYPE_MODE_AC: + proto_serialize_mode_ac(packet, buf); + break; + + case PACKET_TYPE_MODE_S_SHORT: proto_serialize_mode_s_short(packet, buf); break; diff --git a/adsbus/raw.c b/adsbus/raw.c index 41e4309..6e3668d 100644 --- a/adsbus/raw.c +++ b/adsbus/raw.c @@ -9,94 +9,49 @@ #include "raw.h" -struct __attribute__((packed)) raw_mode_s_short_overlay { - char asterisk; - uint8_t payload[14]; +struct __attribute__((packed)) raw_overlay { char semicolon; char cr_lf; char lf; }; -struct __attribute__((packed)) raw_mode_s_long_overlay { - char asterisk; - uint8_t payload[28]; - char semicolon; - char cr_lf; - char lf; -}; +static bool raw_parse_packet(struct buf *buf, struct packet *packet, enum packet_type type) { + size_t payload_bytes = packet_payload_len[type]; + size_t overlay_start = 1 + payload_bytes; + struct raw_overlay *overlay = (struct raw_overlay *) buf_at(buf, overlay_start); + size_t total_len = overlay_start + sizeof(*overlay); -static bool raw_parse_mode_s_short(struct buf *buf, struct packet *packet) { - struct raw_mode_s_short_overlay *overlay = (struct raw_mode_s_short_overlay *) buf_at(buf, 0); if (((buf->length < sizeof(*overlay) - 1 || overlay->cr_lf != '\n') && (buf->length < sizeof(*overlay) || overlay->cr_lf != '\r' || overlay->lf != '\n')) || - overlay->asterisk != '*' || + buf_chr(buf, 0) != '*' || overlay->semicolon != ';') { return false; } - if (!hex_to_bin(packet->payload, overlay->payload, sizeof(overlay->payload) / 2)) { + if (!hex_to_bin(packet->payload, buf_at(buf, 1), payload_bytes)) { return false; } - packet->type = PACKET_TYPE_MODE_S_SHORT; - buf_consume(buf, overlay->cr_lf == '\r' ? sizeof(*overlay) : sizeof(*overlay) - 1); + packet->type = type; + buf_consume(buf, overlay->cr_lf == '\r' ? total_len : total_len - 1); return true; } -static bool raw_parse_mode_s_long(struct buf *buf, struct packet *packet) { - struct raw_mode_s_long_overlay *overlay = (struct raw_mode_s_long_overlay *) buf_at(buf, 0); - if (((buf->length < sizeof(*overlay) - 1 || overlay->cr_lf != '\n') && - (buf->length < sizeof(*overlay) || overlay->cr_lf != '\r' || overlay->lf != '\n')) || - overlay->asterisk != '*' || - overlay->semicolon != ';') { - return false; - } - if (!hex_to_bin(packet->payload, overlay->payload, sizeof(overlay->payload) / 2)) { - return false; - } - packet->type = PACKET_TYPE_MODE_S_LONG; - buf_consume(buf, overlay->cr_lf == '\r' ? sizeof(*overlay) : sizeof(*overlay) - 1); - return true; -} - -static void raw_serialize_mode_s_short(struct packet *packet, struct buf *buf) { - struct raw_mode_s_short_overlay *overlay = (struct raw_mode_s_short_overlay *) buf_at(buf, 0); - overlay->asterisk = '*'; - overlay->semicolon = ';'; - overlay->lf = '\n'; - hex_from_bin_upper(overlay->payload, packet->payload, sizeof(overlay->payload) / 2); - buf->length = sizeof(*overlay); -} - -static void raw_serialize_mode_s_long(struct packet *packet, struct buf *buf) { - struct raw_mode_s_long_overlay *overlay = (struct raw_mode_s_long_overlay *) buf_at(buf, 0); - overlay->asterisk = '*'; - overlay->semicolon = ';'; - overlay->lf = '\n'; - hex_from_bin_upper(overlay->payload, packet->payload, sizeof(overlay->payload) / 2); - buf->length = sizeof(*overlay); -} - void raw_init() { - assert(sizeof(struct raw_mode_s_short_overlay) < BUF_LEN_MAX); - assert(sizeof(struct raw_mode_s_long_overlay) < BUF_LEN_MAX); + assert(1 + PACKET_PAYLOAD_LEN_MAX + sizeof(struct raw_overlay) < BUF_LEN_MAX); } bool raw_parse(struct buf *buf, struct packet *packet, void __attribute__((unused)) *state_in) { return ( - raw_parse_mode_s_short(buf, packet) || - raw_parse_mode_s_long(buf, packet)); + raw_parse_packet(buf, packet, PACKET_TYPE_MODE_AC) || + raw_parse_packet(buf, packet, PACKET_TYPE_MODE_S_SHORT) || + raw_parse_packet(buf, packet, PACKET_TYPE_MODE_S_LONG)); } void raw_serialize(struct packet *packet, struct buf *buf) { - switch (packet->type) { - case PACKET_TYPE_NONE: - break; - - case PACKET_TYPE_MODE_S_SHORT: - raw_serialize_mode_s_short(packet, buf); - break; - - case PACKET_TYPE_MODE_S_LONG: - raw_serialize_mode_s_long(packet, buf); - break; - } + size_t payload_bytes = packet_payload_len[packet->type]; + struct raw_overlay *overlay = (struct raw_overlay *) buf_at(buf, 1 + payload_bytes); + buf_chr(buf, 0) = '*'; + overlay->semicolon = ';'; + overlay->lf = '\n'; + hex_from_bin_upper(buf_at(buf, 1), packet->payload, payload_bytes); + buf->length = 1 + payload_bytes + sizeof(*overlay); } diff --git a/proto/adsb.proto b/proto/adsb.proto index e9bf4fc..870d215 100644 --- a/proto/adsb.proto +++ b/proto/adsb.proto @@ -17,8 +17,9 @@ message AdsbPacket { message Adsb { oneof record { AdsbHeader header = 1; - AdsbPacket mode_s_short = 2; - AdsbPacket mode_s_long = 3; + AdsbPacket mode_ac = 2; + AdsbPacket mode_s_short = 3; + AdsbPacket mode_s_long = 4; } }