1 /* Mode1090, a Mode S messages decoder for RTLSDR devices.
2 *
3 * Copyright (C) 2012 by Salvatore Sanfilippo <antirez@gmail.com>
4 *
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <pthread.h>
35 #include <stdint.h>
36 #include <errno.h>
37 #include <unistd.h>
38 #include <math.h>
39 #include <sys/time.h>
40 #include <signal.h>
41 #include <fcntl.h>
42 #include <ctype.h>
43 #include <sys/stat.h>
44 #include <sys/ioctl.h>
45 #include <sys/select.h>
46 #include "rtl-sdr.h"
47 #include "anet.h"
48
49 #define MODES_DEFAULT_RATE 2000000
50 #define MODES_DEFAULT_FREQ 1090000000
51 #define MODES_DEFAULT_WIDTH 1000
52 #define MODES_DEFAULT_HEIGHT 700
53 #define MODES_ASYNC_BUF_NUMBER 12
54 #define MODES_DATA_LEN (16*16384) /* 256k */
55 #define MODES_AUTO_GAIN -100 /* Use automatic gain. */
56 #define MODES_MAX_GAIN 999999 /* Use max available gain. */
57
58 #define MODES_PREAMBLE_US 8 /* microseconds */
59 #define MODES_LONG_MSG_BITS 112
60 #define MODES_SHORT_MSG_BITS 56
61 #define MODES_FULL_LEN (MODES_PREAMBLE_US+MODES_LONG_MSG_BITS)
62 #define MODES_LONG_MSG_BYTES (112/8)
63 #define MODES_SHORT_MSG_BYTES (56/8)
64
65 #define MODES_ICAO_CACHE_LEN 1024 /* Power of two required. */
66 #define MODES_ICAO_CACHE_TTL 60 /* Time to live of cached addresses. */
67 #define MODES_UNIT_FEET 0
68 #define MODES_UNIT_METERS 1
69
70 #define MODES_DEBUG_DEMOD (1<<0)
71 #define MODES_DEBUG_DEMODERR (1<<1)
72 #define MODES_DEBUG_BADCRC (1<<2)
73 #define MODES_DEBUG_GOODCRC (1<<3)
74 #define MODES_DEBUG_NOPREAMBLE (1<<4)
75 #define MODES_DEBUG_NET (1<<5)
76 #define MODES_DEBUG_JS (1<<6)
77
78 /* When debug is set to MODES_DEBUG_NOPREAMBLE, the first sample must be
79 * at least greater than a given level for us to dump the signal. */
80 #define MODES_DEBUG_NOPREAMBLE_LEVEL 25
81
82 #define MODES_INTERACTIVE_REFRESH_TIME 250 /* Milliseconds */
83 #define MODES_INTERACTIVE_ROWS 15 /* Rows on screen */
84 #define MODES_INTERACTIVE_TTL 60 /* TTL before being removed */
85
86 #define MODES_NET_MAX_FD 1024
87 #define MODES_NET_OUTPUT_SBS_PORT 30003
88 #define MODES_NET_OUTPUT_RAW_PORT 30002
89 #define MODES_NET_INPUT_RAW_PORT 30001
90 #define MODES_NET_HTTP_PORT 8080
91 #define MODES_CLIENT_BUF_SIZE 1024
92 #define MODES_NET_SNDBUF_SIZE (1024*64)
93
94 #define MODES_NOTUSED(V) ((void) V)
95
96 /* Structure used to describe a networking client. */
97 struct client {
98 int fd; /* File descriptor. */
99 int service; /* TCP port the client is connected to. */
100 char buf[MODES_CLIENT_BUF_SIZE+1]; /* Read buffer. */
101 int buflen; /* Amount of data on buffer. */
102 };
103
104 /* Structure used to describe an aircraft in iteractive mode. */
105 struct aircraft {
106 uint32_t addr; /* ICAO address */
107 char hexaddr[7]; /* Printable ICAO address */
108 char flight[9]; /* Flight number */
109 int altitude; /* Altitude */
110 int speed; /* Velocity computed from EW and NS components. */
111 int track; /* Angle of flight. */
112 time_t seen; /* Time at which the last packet was received. */
113 long messages; /* Number of Mode S messages received. */
114 /* Encoded latitude and longitude as extracted by odd and even
115 * CPR encoded messages. */
116 int odd_cprlat;
117 int odd_cprlon;
118 int even_cprlat;
119 int even_cprlon;
120 double lat, lon; /* Coordinated obtained from CPR encoded data. */
121 long long odd_cprtime, even_cprtime;
122 struct aircraft *next; /* Next aircraft in our linked list. */
123 };
124
125 /* Program global state. */
126 struct {
127 /* Internal state */
128 pthread_t reader_thread;
129 pthread_mutex_t data_mutex; /* Mutex to synchronize buffer access. */
130 pthread_cond_t data_cond; /* Conditional variable associated. */
131 unsigned char *data; /* Raw IQ samples buffer */
132 uint16_t *magnitude; /* Magnitude vector */
133 uint32_t data_len; /* Buffer length. */
134 int fd; /* --ifile option file descriptor. */
135 int data_ready; /* Data ready to be processed. */
136 uint32_t *icao_cache; /* Recently seen ICAO addresses cache. */
137 uint16_t *maglut; /* I/Q -> Magnitude lookup table. */
138 int exit; /* Exit from the main loop when true. */
139
140 /* RTLSDR */
141 int dev_index;
142 int gain;
143 int enable_agc;
144 rtlsdr_dev_t *dev;
145 int freq;
146
147 /* Networking */
148 char aneterr[ANET_ERR_LEN];
149 struct client *clients[MODES_NET_MAX_FD]; /* Our clients. */
150 int maxfd; /* Greatest fd currently active. */
151 int sbsos; /* SBS output listening socket. */
152 int ros; /* Raw output listening socket. */
153 int ris; /* Raw input listening socket. */
154 int https; /* HTTP listening socket. */
155
156 /* Configuration */
157 char *filename; /* Input form file, --ifile option. */
158 int loop; /* Read input file again and again. */
159 int fix_errors; /* Single bit error correction if true. */
160 int check_crc; /* Only display messages with good CRC. */
161 int raw; /* Raw output format. */
162 int debug; /* Debugging mode. */
163 int net; /* Enable networking. */
164 int net_only; /* Enable just networking. */
165 int interactive; /* Interactive mode */
166 int interactive_rows; /* Interactive mode: max number of rows. */
167 int interactive_ttl; /* Interactive mode: TTL before deletion. */
168 int stats; /* Print stats at exit in --ifile mode. */
169 int onlyaddr; /* Print only ICAO addresses. */
170 int metric; /* Use metric units. */
171 int aggressive; /* Aggressive detection algorithm. */
172
173 /* Interactive mode */
174 struct aircraft *aircrafts;
175 long long interactive_last_update; /* Last screen update in milliseconds */
176
177 /* Statistics */
178 long long stat_valid_preamble;
179 long long stat_demodulated;
180 long long stat_goodcrc;
181 long long stat_badcrc;
182 long long stat_fixed;
183 long long stat_single_bit_fix;
184 long long stat_two_bits_fix;
185 long long stat_http_requests;
186 long long stat_sbs_connections;
187 long long stat_out_of_phase;
188 } Modes;
189
190 /* The struct we use to store information about a decoded message. */
191 struct modesMessage {
192 /* Generic fields */
193 unsigned char msg[MODES_LONG_MSG_BYTES]; /* Binary message. */
194 int msgbits; /* Number of bits in message */
195 int msgtype; /* Downlink format # */
196 int crcok; /* True if CRC was valid */
197 uint32_t crc; /* Message CRC */
198 int errorbit; /* Bit corrected. -1 if no bit corrected. */
199 int aa1, aa2, aa3; /* ICAO Address bytes 1 2 and 3 */
200 int phase_corrected; /* True if phase correction was applied. */
201
202 /* DF 11 */
203 int ca; /* Responder capabilities. */
204
205 /* DF 17 */
206 int metype; /* Extended squitter message type. */
207 int mesub; /* Extended squitter message subtype. */
208 int heading_is_valid;
209 int heading;
210 int aircraft_type;
211 int fflag; /* 1 = Odd, 0 = Even CPR message. */
212 int tflag; /* UTC synchronized? */
213 int raw_latitude; /* Non decoded latitude */
214 int raw_longitude; /* Non decoded longitude */
215 char flight[9]; /* 8 chars flight number. */
216 int ew_dir; /* 0 = East, 1 = West. */
217 int ew_velocity; /* E/W velocity. */
218 int ns_dir; /* 0 = North, 1 = South. */
219 int ns_velocity; /* N/S velocity. */
220 int vert_rate_source; /* Vertical rate source. */
221 int vert_rate_sign; /* Vertical rate sign. */
222 int vert_rate; /* Vertical rate. */
223 int velocity; /* Computed from EW and NS velocity. */
224
225 /* DF4, DF5, DF20, DF21 */
226 int fs; /* Flight status for DF4,5,20,21 */
227 int dr; /* Request extraction of downlink request. */
228 int um; /* Request extraction of downlink request. */
229 int identity; /* 13 bits identity (Squawk). */
230
231 /* Fields used by multiple message types. */
232 int altitude, unit;
233 };
234
235 void interactiveShowData(void);
236 struct aircraft* interactiveReceiveData(struct modesMessage *mm);
237 void modesSendRawOutput(struct modesMessage *mm);
238 void modesSendSBSOutput(struct modesMessage *mm, struct aircraft *a);
239 void useModesMessage(struct modesMessage *mm);
240 int fixSingleBitErrors(unsigned char *msg, int bits);
241 int fixTwoBitsErrors(unsigned char *msg, int bits);
242 int modesMessageLenByType(int type);
243 void sigWinchCallback();
244 int getTermRows();
245
246 /* ============================= Utility functions ========================== */
247
mstime(void)248 static long long mstime(void) {
249 struct timeval tv;
250 long long mst;
251
252 gettimeofday(&tv, NULL);
253 mst = ((long long)tv.tv_sec)*1000;
254 mst += tv.tv_usec/1000;
255 return mst;
256 }
257
258 /* =============================== Initialization =========================== */
259
modesInitConfig(void)260 void modesInitConfig(void) {
261 Modes.gain = MODES_MAX_GAIN;
262 Modes.dev_index = 0;
263 Modes.enable_agc = 0;
264 Modes.freq = MODES_DEFAULT_FREQ;
265 Modes.filename = NULL;
266 Modes.fix_errors = 1;
267 Modes.check_crc = 1;
268 Modes.raw = 0;
269 Modes.net = 0;
270 Modes.net_only = 0;
271 Modes.onlyaddr = 0;
272 Modes.debug = 0;
273 Modes.interactive = 0;
274 Modes.interactive_rows = MODES_INTERACTIVE_ROWS;
275 Modes.interactive_ttl = MODES_INTERACTIVE_TTL;
276 Modes.aggressive = 0;
277 Modes.interactive_rows = getTermRows();
278 Modes.loop = 0;
279 }
280
modesInit(void)281 void modesInit(void) {
282 int i, q;
283
284 pthread_mutex_init(&Modes.data_mutex,NULL);
285 pthread_cond_init(&Modes.data_cond,NULL);
286 /* We add a full message minus a final bit to the length, so that we
287 * can carry the remaining part of the buffer that we can't process
288 * in the message detection loop, back at the start of the next data
289 * to process. This way we are able to also detect messages crossing
290 * two reads. */
291 Modes.data_len = MODES_DATA_LEN + (MODES_FULL_LEN-1)*4;
292 Modes.data_ready = 0;
293 /* Allocate the ICAO address cache. We use two uint32_t for every
294 * entry because it's a addr / timestamp pair for every entry. */
295 Modes.icao_cache = malloc(sizeof(uint32_t)*MODES_ICAO_CACHE_LEN*2);
296 memset(Modes.icao_cache,0,sizeof(uint32_t)*MODES_ICAO_CACHE_LEN*2);
297 Modes.aircrafts = NULL;
298 Modes.interactive_last_update = 0;
299 if ((Modes.data = malloc(Modes.data_len)) == NULL ||
300 (Modes.magnitude = malloc(Modes.data_len*2)) == NULL) {
301 fprintf(stderr, "Out of memory allocating data buffer.\n");
302 exit(1);
303 }
304 memset(Modes.data,127,Modes.data_len);
305
306 /* Populate the I/Q -> Magnitude lookup table. It is used because
307 * sqrt or round may be expensive and may vary a lot depending on
308 * the libc used.
309 *
310 * We scale to 0-255 range multiplying by 1.4 in order to ensure that
311 * every different I/Q pair will result in a different magnitude value,
312 * not losing any resolution. */
313 Modes.maglut = malloc(129*129*2);
314 for (i = 0; i <= 128; i++) {
315 for (q = 0; q <= 128; q++) {
316 Modes.maglut[i*129+q] = round(sqrt(i*i+q*q)*360);
317 }
318 }
319
320 /* Statistics */
321 Modes.stat_valid_preamble = 0;
322 Modes.stat_demodulated = 0;
323 Modes.stat_goodcrc = 0;
324 Modes.stat_badcrc = 0;
325 Modes.stat_fixed = 0;
326 Modes.stat_single_bit_fix = 0;
327 Modes.stat_two_bits_fix = 0;
328 Modes.stat_http_requests = 0;
329 Modes.stat_sbs_connections = 0;
330 Modes.stat_out_of_phase = 0;
331 Modes.exit = 0;
332 }
333
334 /* =============================== RTLSDR handling ========================== */
335
modesInitRTLSDR(void)336 void modesInitRTLSDR(void) {
337 int j;
338 int device_count;
339 int ppm_error = 0;
340 char vendor[256], product[256], serial[256];
341
342 device_count = rtlsdr_get_device_count();
343 if (!device_count) {
344 fprintf(stderr, "No supported RTLSDR devices found.\n");
345 exit(1);
346 }
347
348 fprintf(stderr, "Found %d device(s):\n", device_count);
349 for (j = 0; j < device_count; j++) {
350 rtlsdr_get_device_usb_strings(j, vendor, product, serial);
351 fprintf(stderr, "%d: %s, %s, SN: %s %s\n", j, vendor, product, serial,
352 (j == Modes.dev_index) ? "(currently selected)" : "");
353 }
354
355 if (rtlsdr_open(&Modes.dev, Modes.dev_index) < 0) {
356 fprintf(stderr, "Error opening the RTLSDR device: %s\n",
357 strerror(errno));
358 exit(1);
359 }
360
361 /* Set gain, frequency, sample rate, and reset the device. */
362 rtlsdr_set_tuner_gain_mode(Modes.dev,
363 (Modes.gain == MODES_AUTO_GAIN) ? 0 : 1);
364 if (Modes.gain != MODES_AUTO_GAIN) {
365 if (Modes.gain == MODES_MAX_GAIN) {
366 /* Find the maximum gain available. */
367 int numgains;
368 int gains[100];
369
370 numgains = rtlsdr_get_tuner_gains(Modes.dev, gains);
371 Modes.gain = gains[numgains-1];
372 fprintf(stderr, "Max available gain is: %.2f\n", Modes.gain/10.0);
373 }
374 rtlsdr_set_tuner_gain(Modes.dev, Modes.gain);
375 fprintf(stderr, "Setting gain to: %.2f\n", Modes.gain/10.0);
376 } else {
377 fprintf(stderr, "Using automatic gain control.\n");
378 }
379 rtlsdr_set_freq_correction(Modes.dev, ppm_error);
380 if (Modes.enable_agc) rtlsdr_set_agc_mode(Modes.dev, 1);
381 rtlsdr_set_center_freq(Modes.dev, Modes.freq);
382 rtlsdr_set_sample_rate(Modes.dev, MODES_DEFAULT_RATE);
383 rtlsdr_reset_buffer(Modes.dev);
384 fprintf(stderr, "Gain reported by device: %.2f\n",
385 rtlsdr_get_tuner_gain(Modes.dev)/10.0);
386 }
387
388 /* We use a thread reading data in background, while the main thread
389 * handles decoding and visualization of data to the user.
390 *
391 * The reading thread calls the RTLSDR API to read data asynchronously, and
392 * uses a callback to populate the data buffer.
393 * A Mutex is used to avoid races with the decoding thread. */
rtlsdrCallback(unsigned char * buf,uint32_t len,void * ctx)394 void rtlsdrCallback(unsigned char *buf, uint32_t len, void *ctx) {
395 MODES_NOTUSED(ctx);
396
397 pthread_mutex_lock(&Modes.data_mutex);
398 if (len > MODES_DATA_LEN) len = MODES_DATA_LEN;
399 /* Move the last part of the previous buffer, that was not processed,
400 * on the start of the new buffer. */
401 memcpy(Modes.data, Modes.data+MODES_DATA_LEN, (MODES_FULL_LEN-1)*4);
402 /* Read the new data. */
403 memcpy(Modes.data+(MODES_FULL_LEN-1)*4, buf, len);
404 Modes.data_ready = 1;
405 /* Signal to the other thread that new data is ready */
406 pthread_cond_signal(&Modes.data_cond);
407 pthread_mutex_unlock(&Modes.data_mutex);
408 }
409
410 /* This is used when --ifile is specified in order to read data from file
411 * instead of using an RTLSDR device. */
readDataFromFile(void)412 void readDataFromFile(void) {
413 pthread_mutex_lock(&Modes.data_mutex);
414 while(1) {
415 ssize_t nread, toread;
416 unsigned char *p;
417
418 if (Modes.data_ready) {
419 pthread_cond_wait(&Modes.data_cond,&Modes.data_mutex);
420 continue;
421 }
422
423 if (Modes.interactive) {
424 /* When --ifile and --interactive are used together, slow down
425 * playing at the natural rate of the RTLSDR received. */
426 pthread_mutex_unlock(&Modes.data_mutex);
427 usleep(5000);
428 pthread_mutex_lock(&Modes.data_mutex);
429 }
430
431 /* Move the last part of the previous buffer, that was not processed,
432 * on the start of the new buffer. */
433 memcpy(Modes.data, Modes.data+MODES_DATA_LEN, (MODES_FULL_LEN-1)*4);
434 toread = MODES_DATA_LEN;
435 p = Modes.data+(MODES_FULL_LEN-1)*4;
436 while(toread) {
437 nread = read(Modes.fd, p, toread);
438 /* In --file mode, seek the file again from the start
439 * and re-play it if --loop was given. */
440 if (nread == 0 &&
441 Modes.filename != NULL &&
442 Modes.fd != STDIN_FILENO &&
443 Modes.loop)
444 {
445 if (lseek(Modes.fd,0,SEEK_SET) != -1) continue;
446 }
447
448 if (nread <= 0) {
449 Modes.exit = 1; /* Signal the other thread to exit. */
450 break;
451 }
452 p += nread;
453 toread -= nread;
454 }
455 if (toread) {
456 /* Not enough data on file to fill the buffer? Pad with
457 * no signal. */
458 memset(p,127,toread);
459 }
460 Modes.data_ready = 1;
461 /* Signal to the other thread that new data is ready */
462 pthread_cond_signal(&Modes.data_cond);
463 }
464 }
465
466 /* We read data using a thread, so the main thread only handles decoding
467 * without caring about data acquisition. */
readerThreadEntryPoint(void * arg)468 void *readerThreadEntryPoint(void *arg) {
469 MODES_NOTUSED(arg);
470
471 if (Modes.filename == NULL) {
472 rtlsdr_read_async(Modes.dev, rtlsdrCallback, NULL,
473 MODES_ASYNC_BUF_NUMBER,
474 MODES_DATA_LEN);
475 } else {
476 readDataFromFile();
477 }
478 return NULL;
479 }
480
481 /* ============================== Debugging ================================= */
482
483 /* Helper function for dumpMagnitudeVector().
484 * It prints a single bar used to display raw signals.
485 *
486 * Since every magnitude sample is between 0-255, the function uses
487 * up to 63 characters for every bar. Every character represents
488 * a length of 4, 3, 2, 1, specifically:
489 *
490 * "O" is 4
491 * "o" is 3
492 * "-" is 2
493 * "." is 1
494 */
dumpMagnitudeBar(int index,int magnitude)495 void dumpMagnitudeBar(int index, int magnitude) {
496 char *set = " .-o";
497 char buf[256];
498 int div = magnitude / 256 / 4;
499 int rem = magnitude / 256 % 4;
500
501 memset(buf,'O',div);
502 buf[div] = set[rem];
503 buf[div+1] = '\0';
504
505 if (index >= 0) {
506 int markchar = ']';
507
508 /* preamble peaks are marked with ">" */
509 if (index == 0 || index == 2 || index == 7 || index == 9)
510 markchar = '>';
511 /* Data peaks are marked to distinguish pairs of bits. */
512 if (index >= 16) markchar = ((index-16)/2 & 1) ? '|' : ')';
513 printf("[%.3d%c |%-66s %d\n", index, markchar, buf, magnitude);
514 } else {
515 printf("[%.2d] |%-66s %d\n", index, buf, magnitude);
516 }
517 }
518
519 /* Display an ASCII-art alike graphical representation of the undecoded
520 * message as a magnitude signal.
521 *
522 * The message starts at the specified offset in the "m" buffer.
523 * The function will display enough data to cover a short 56 bit message.
524 *
525 * If possible a few samples before the start of the messsage are included
526 * for context. */
527
dumpMagnitudeVector(uint16_t * m,uint32_t offset)528 void dumpMagnitudeVector(uint16_t *m, uint32_t offset) {
529 uint32_t padding = 5; /* Show a few samples before the actual start. */
530 uint32_t start = (offset < padding) ? 0 : offset-padding;
531 uint32_t end = offset + (MODES_PREAMBLE_US*2)+(MODES_SHORT_MSG_BITS*2) - 1;
532 uint32_t j;
533
534 for (j = start; j <= end; j++) {
535 dumpMagnitudeBar(j-offset, m[j]);
536 }
537 }
538
539 /* Produce a raw representation of the message as a Javascript file
540 * loadable by debug.html. */
dumpRawMessageJS(char * descr,unsigned char * msg,uint16_t * m,uint32_t offset,int fixable)541 void dumpRawMessageJS(char *descr, unsigned char *msg,
542 uint16_t *m, uint32_t offset, int fixable)
543 {
544 int padding = 5; /* Show a few samples before the actual start. */
545 int start = offset - padding;
546 int end = offset + (MODES_PREAMBLE_US*2)+(MODES_LONG_MSG_BITS*2) - 1;
547 FILE *fp;
548 int j, fix1 = -1, fix2 = -1;
549
550 if (fixable != -1) {
551 fix1 = fixable & 0xff;
552 if (fixable > 255) fix2 = fixable >> 8;
553 }
554
555 if ((fp = fopen("frames.js","a")) == NULL) {
556 fprintf(stderr, "Error opening frames.js: %s\n", strerror(errno));
557 exit(1);
558 }
559
560 fprintf(fp,"frames.push({\"descr\": \"%s\", \"mag\": [", descr);
561 for (j = start; j <= end; j++) {
562 fprintf(fp,"%d", j < 0 ? 0 : m[j]);
563 if (j != end) fprintf(fp,",");
564 }
565 fprintf(fp,"], \"fix1\": %d, \"fix2\": %d, \"bits\": %d, \"hex\": \"",
566 fix1, fix2, modesMessageLenByType(msg[0]>>3));
567 for (j = 0; j < MODES_LONG_MSG_BYTES; j++)
568 fprintf(fp,"\\x%02x",msg[j]);
569 fprintf(fp,"\"});\n");
570 fclose(fp);
571 }
572
573 /* This is a wrapper for dumpMagnitudeVector() that also show the message
574 * in hex format with an additional description.
575 *
576 * descr is the additional message to show to describe the dump.
577 * msg points to the decoded message
578 * m is the original magnitude vector
579 * offset is the offset where the message starts
580 *
581 * The function also produces the Javascript file used by debug.html to
582 * display packets in a graphical format if the Javascript output was
583 * enabled.
584 */
dumpRawMessage(char * descr,unsigned char * msg,uint16_t * m,uint32_t offset)585 void dumpRawMessage(char *descr, unsigned char *msg,
586 uint16_t *m, uint32_t offset)
587 {
588 int j;
589 int msgtype = msg[0]>>3;
590 int fixable = -1;
591
592 if (msgtype == 11 || msgtype == 17) {
593 int msgbits = (msgtype == 11) ? MODES_SHORT_MSG_BITS :
594 MODES_LONG_MSG_BITS;
595 fixable = fixSingleBitErrors(msg,msgbits);
596 if (fixable == -1)
597 fixable = fixTwoBitsErrors(msg,msgbits);
598 }
599
600 if (Modes.debug & MODES_DEBUG_JS) {
601 dumpRawMessageJS(descr, msg, m, offset, fixable);
602 return;
603 }
604
605 printf("\n--- %s\n ", descr);
606 for (j = 0; j < MODES_LONG_MSG_BYTES; j++) {
607 printf("%02x",msg[j]);
608 if (j == MODES_SHORT_MSG_BYTES-1) printf(" ... ");
609 }
610 printf(" (DF %d, Fixable: %d)\n", msgtype, fixable);
611 dumpMagnitudeVector(m,offset);
612 printf("---\n\n");
613 }
614
615 /* ===================== Mode S detection and decoding ===================== */
616
617 /* Parity table for MODE S Messages.
618 * The table contains 112 elements, every element corresponds to a bit set
619 * in the message, starting from the first bit of actual data after the
620 * preamble.
621 *
622 * For messages of 112 bit, the whole table is used.
623 * For messages of 56 bits only the last 56 elements are used.
624 *
625 * The algorithm is as simple as xoring all the elements in this table
626 * for which the corresponding bit on the message is set to 1.
627 *
628 * The latest 24 elements in this table are set to 0 as the checksum at the
629 * end of the message should not affect the computation.
630 *
631 * Note: this function can be used with DF11 and DF17, other modes have
632 * the CRC xored with the sender address as they are reply to interrogations,
633 * but a casual listener can't split the address from the checksum.
634 */
635 uint32_t modes_checksum_table[112] = {
636 0x3935ea, 0x1c9af5, 0xf1b77e, 0x78dbbf, 0xc397db, 0x9e31e9, 0xb0e2f0, 0x587178,
637 0x2c38bc, 0x161c5e, 0x0b0e2f, 0xfa7d13, 0x82c48d, 0xbe9842, 0x5f4c21, 0xd05c14,
638 0x682e0a, 0x341705, 0xe5f186, 0x72f8c3, 0xc68665, 0x9cb936, 0x4e5c9b, 0xd8d449,
639 0x939020, 0x49c810, 0x24e408, 0x127204, 0x093902, 0x049c81, 0xfdb444, 0x7eda22,
640 0x3f6d11, 0xe04c8c, 0x702646, 0x381323, 0xe3f395, 0x8e03ce, 0x4701e7, 0xdc7af7,
641 0x91c77f, 0xb719bb, 0xa476d9, 0xadc168, 0x56e0b4, 0x2b705a, 0x15b82d, 0xf52612,
642 0x7a9309, 0xc2b380, 0x6159c0, 0x30ace0, 0x185670, 0x0c2b38, 0x06159c, 0x030ace,
643 0x018567, 0xff38b7, 0x80665f, 0xbfc92b, 0xa01e91, 0xaff54c, 0x57faa6, 0x2bfd53,
644 0xea04ad, 0x8af852, 0x457c29, 0xdd4410, 0x6ea208, 0x375104, 0x1ba882, 0x0dd441,
645 0xf91024, 0x7c8812, 0x3e4409, 0xe0d800, 0x706c00, 0x383600, 0x1c1b00, 0x0e0d80,
646 0x0706c0, 0x038360, 0x01c1b0, 0x00e0d8, 0x00706c, 0x003836, 0x001c1b, 0xfff409,
647 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
648 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
649 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000
650 };
651
modesChecksum(unsigned char * msg,int bits)652 uint32_t modesChecksum(unsigned char *msg, int bits) {
653 uint32_t crc = 0;
654 int offset = (bits == 112) ? 0 : (112-56);
655 int j;
656
657 for(j = 0; j < bits; j++) {
658 int byte = j/8;
659 int bit = j%8;
660 int bitmask = 1 << (7-bit);
661
662 /* If bit is set, xor with corresponding table entry. */
663 if (msg[byte] & bitmask)
664 crc ^= modes_checksum_table[j+offset];
665 }
666 return crc; /* 24 bit checksum. */
667 }
668
669 /* Given the Downlink Format (DF) of the message, return the message length
670 * in bits. */
modesMessageLenByType(int type)671 int modesMessageLenByType(int type) {
672 if (type == 16 || type == 17 ||
673 type == 19 || type == 20 ||
674 type == 21)
675 return MODES_LONG_MSG_BITS;
676 else
677 return MODES_SHORT_MSG_BITS;
678 }
679
680 /* Try to fix single bit errors using the checksum. On success modifies
681 * the original buffer with the fixed version, and returns the position
682 * of the error bit. Otherwise if fixing failed -1 is returned. */
fixSingleBitErrors(unsigned char * msg,int bits)683 int fixSingleBitErrors(unsigned char *msg, int bits) {
684 int j;
685 unsigned char aux[MODES_LONG_MSG_BITS/8];
686
687 for (j = 0; j < bits; j++) {
688 int byte = j/8;
689 int bitmask = 1 << (7-(j%8));
690 uint32_t crc1, crc2;
691
692 memcpy(aux,msg,bits/8);
693 aux[byte] ^= bitmask; /* Flip j-th bit. */
694
695 crc1 = ((uint32_t)aux[(bits/8)-3] << 16) |
696 ((uint32_t)aux[(bits/8)-2] << 8) |
697 (uint32_t)aux[(bits/8)-1];
698 crc2 = modesChecksum(aux,bits);
699
700 if (crc1 == crc2) {
701 /* The error is fixed. Overwrite the original buffer with
702 * the corrected sequence, and returns the error bit
703 * position. */
704 memcpy(msg,aux,bits/8);
705 return j;
706 }
707 }
708 return -1;
709 }
710
711 /* Similar to fixSingleBitErrors() but try every possible two bit combination.
712 * This is very slow and should be tried only against DF17 messages that
713 * don't pass the checksum, and only in Aggressive Mode. */
fixTwoBitsErrors(unsigned char * msg,int bits)714 int fixTwoBitsErrors(unsigned char *msg, int bits) {
715 int j, i;
716 unsigned char aux[MODES_LONG_MSG_BITS/8];
717
718 for (j = 0; j < bits; j++) {
719 int byte1 = j/8;
720 int bitmask1 = 1 << (7-(j%8));
721
722 /* Don't check the same pairs multiple times, so i starts from j+1 */
723 for (i = j+1; i < bits; i++) {
724 int byte2 = i/8;
725 int bitmask2 = 1 << (7-(i%8));
726 uint32_t crc1, crc2;
727
728 memcpy(aux,msg,bits/8);
729
730 aux[byte1] ^= bitmask1; /* Flip j-th bit. */
731 aux[byte2] ^= bitmask2; /* Flip i-th bit. */
732
733 crc1 = ((uint32_t)aux[(bits/8)-3] << 16) |
734 ((uint32_t)aux[(bits/8)-2] << 8) |
735 (uint32_t)aux[(bits/8)-1];
736 crc2 = modesChecksum(aux,bits);
737
738 if (crc1 == crc2) {
739 /* The error is fixed. Overwrite the original buffer with
740 * the corrected sequence, and returns the error bit
741 * position. */
742 memcpy(msg,aux,bits/8);
743 /* We return the two bits as a 16 bit integer by shifting
744 * 'i' on the left. This is possible since 'i' will always
745 * be non-zero because i starts from j+1. */
746 return j | (i<<8);
747 }
748 }
749 }
750 return -1;
751 }
752
753 /* Hash the ICAO address to index our cache of MODES_ICAO_CACHE_LEN
754 * elements, that is assumed to be a power of two. */
ICAOCacheHashAddress(uint32_t a)755 uint32_t ICAOCacheHashAddress(uint32_t a) {
756 /* The following three rounds wil make sure that every bit affects
757 * every output bit with ~ 50% of probability. */
758 a = ((a >> 16) ^ a) * 0x45d9f3b;
759 a = ((a >> 16) ^ a) * 0x45d9f3b;
760 a = ((a >> 16) ^ a);
761 return a & (MODES_ICAO_CACHE_LEN-1);
762 }
763
764 /* Add the specified entry to the cache of recently seen ICAO addresses.
765 * Note that we also add a timestamp so that we can make sure that the
766 * entry is only valid for MODES_ICAO_CACHE_TTL seconds. */
addRecentlySeenICAOAddr(uint32_t addr)767 void addRecentlySeenICAOAddr(uint32_t addr) {
768 uint32_t h = ICAOCacheHashAddress(addr);
769 Modes.icao_cache[h*2] = addr;
770 Modes.icao_cache[h*2+1] = (uint32_t) time(NULL);
771 }
772
773 /* Returns 1 if the specified ICAO address was seen in a DF format with
774 * proper checksum (not xored with address) no more than * MODES_ICAO_CACHE_TTL
775 * seconds ago. Otherwise returns 0. */
ICAOAddressWasRecentlySeen(uint32_t addr)776 int ICAOAddressWasRecentlySeen(uint32_t addr) {
777 uint32_t h = ICAOCacheHashAddress(addr);
778 uint32_t a = Modes.icao_cache[h*2];
779 uint32_t t = Modes.icao_cache[h*2+1];
780
781 return a && a == addr && time(NULL)-t <= MODES_ICAO_CACHE_TTL;
782 }
783
784 /* If the message type has the checksum xored with the ICAO address, try to
785 * brute force it using a list of recently seen ICAO addresses.
786 *
787 * Do this in a brute-force fashion by xoring the predicted CRC with
788 * the address XOR checksum field in the message. This will recover the
789 * address: if we found it in our cache, we can assume the message is ok.
790 *
791 * This function expects mm->msgtype and mm->msgbits to be correctly
792 * populated by the caller.
793 *
794 * On success the correct ICAO address is stored in the modesMessage
795 * structure in the aa3, aa2, and aa1 fiedls.
796 *
797 * If the function successfully recovers a message with a correct checksum
798 * it returns 1. Otherwise 0 is returned. */
bruteForceAP(unsigned char * msg,struct modesMessage * mm)799 int bruteForceAP(unsigned char *msg, struct modesMessage *mm) {
800 unsigned char aux[MODES_LONG_MSG_BYTES];
801 int msgtype = mm->msgtype;
802 int msgbits = mm->msgbits;
803
804 if (msgtype == 0 || /* Short air surveillance */
805 msgtype == 4 || /* Surveillance, altitude reply */
806 msgtype == 5 || /* Surveillance, identity reply */
807 msgtype == 16 || /* Long Air-Air survillance */
808 msgtype == 20 || /* Comm-A, altitude request */
809 msgtype == 21 || /* Comm-A, identity request */
810 msgtype == 24) /* Comm-C ELM */
811 {
812 uint32_t addr;
813 uint32_t crc;
814 int lastbyte = (msgbits/8)-1;
815
816 /* Work on a copy. */
817 memcpy(aux,msg,msgbits/8);
818
819 /* Compute the CRC of the message and XOR it with the AP field
820 * so that we recover the address, because:
821 *
822 * (ADDR xor CRC) xor CRC = ADDR. */
823 crc = modesChecksum(aux,msgbits);
824 aux[lastbyte] ^= crc & 0xff;
825 aux[lastbyte-1] ^= (crc >> 8) & 0xff;
826 aux[lastbyte-2] ^= (crc >> 16) & 0xff;
827
828 /* If the obtained address exists in our cache we consider
829 * the message valid. */
830 addr = aux[lastbyte] | (aux[lastbyte-1] << 8) | (aux[lastbyte-2] << 16);
831 if (ICAOAddressWasRecentlySeen(addr)) {
832 mm->aa1 = aux[lastbyte-2];
833 mm->aa2 = aux[lastbyte-1];
834 mm->aa3 = aux[lastbyte];
835 return 1;
836 }
837 }
838 return 0;
839 }
840
841 /* Decode the 13 bit AC altitude field (in DF 20 and others).
842 * Returns the altitude, and set 'unit' to either MODES_UNIT_METERS
843 * or MDOES_UNIT_FEETS. */
decodeAC13Field(unsigned char * msg,int * unit)844 int decodeAC13Field(unsigned char *msg, int *unit) {
845 int m_bit = msg[3] & (1<<6);
846 int q_bit = msg[3] & (1<<4);
847
848 if (!m_bit) {
849 *unit = MODES_UNIT_FEET;
850 if (q_bit) {
851 /* N is the 11 bit integer resulting from the removal of bit
852 * Q and M */
853 int n = ((msg[2]&31)<<6) |
854 ((msg[3]&0x80)>>2) |
855 ((msg[3]&0x20)>>1) |
856 (msg[3]&15);
857 /* The final altitude is due to the resulting number multiplied
858 * by 25, minus 1000. */
859 return n*25-1000;
860 } else {
861 /* TODO: Implement altitude where Q=0 and M=0 */
862 }
863 } else {
864 *unit = MODES_UNIT_METERS;
865 /* TODO: Implement altitude when meter unit is selected. */
866 }
867 return 0;
868 }
869
870 /* Decode the 12 bit AC altitude field (in DF 17 and others).
871 * Returns the altitude or 0 if it can't be decoded. */
decodeAC12Field(unsigned char * msg,int * unit)872 int decodeAC12Field(unsigned char *msg, int *unit) {
873 int q_bit = msg[5] & 1;
874
875 if (q_bit) {
876 /* N is the 11 bit integer resulting from the removal of bit
877 * Q */
878 *unit = MODES_UNIT_FEET;
879 int n = ((msg[5]>>1)<<4) | ((msg[6]&0xF0) >> 4);
880 /* The final altitude is due to the resulting number multiplied
881 * by 25, minus 1000. */
882 return n*25-1000;
883 } else {
884 return 0;
885 }
886 }
887
888 /* Capability table. */
889 char *ca_str[8] = {
890 /* 0 */ "Level 1 (Survillance Only)",
891 /* 1 */ "Level 2 (DF0,4,5,11)",
892 /* 2 */ "Level 3 (DF0,4,5,11,20,21)",
893 /* 3 */ "Level 4 (DF0,4,5,11,20,21,24)",
894 /* 4 */ "Level 2+3+4 (DF0,4,5,11,20,21,24,code7 - is on ground)",
895 /* 5 */ "Level 2+3+4 (DF0,4,5,11,20,21,24,code7 - is on airborne)",
896 /* 6 */ "Level 2+3+4 (DF0,4,5,11,20,21,24,code7)",
897 /* 7 */ "Level 7 ???"
898 };
899
900 /* Flight status table. */
901 char *fs_str[8] = {
902 /* 0 */ "Normal, Airborne",
903 /* 1 */ "Normal, On the ground",
904 /* 2 */ "ALERT, Airborne",
905 /* 3 */ "ALERT, On the ground",
906 /* 4 */ "ALERT & Special Position Identification. Airborne or Ground",
907 /* 5 */ "Special Position Identification. Airborne or Ground",
908 /* 6 */ "Value 6 is not assigned",
909 /* 7 */ "Value 7 is not assigned"
910 };
911
912 /* ME message type to description table. */
913 char *me_str[] = {
914 };
915
getMEDescription(int metype,int mesub)916 char *getMEDescription(int metype, int mesub) {
917 char *mename = "Unknown";
918
919 if (metype >= 1 && metype <= 4)
920 mename = "Aircraft Identification and Category";
921 else if (metype >= 5 && metype <= 8)
922 mename = "Surface Position";
923 else if (metype >= 9 && metype <= 18)
924 mename = "Airborne Position (Baro Altitude)";
925 else if (metype == 19 && mesub >=1 && mesub <= 4)
926 mename = "Airborne Velocity";
927 else if (metype >= 20 && metype <= 22)
928 mename = "Airborne Position (GNSS Height)";
929 else if (metype == 23 && mesub == 0)
930 mename = "Test Message";
931 else if (metype == 24 && mesub == 1)
932 mename = "Surface System Status";
933 else if (metype == 28 && mesub == 1)
934 mename = "Extended Squitter Aircraft Status (Emergency)";
935 else if (metype == 28 && mesub == 2)
936 mename = "Extended Squitter Aircraft Status (1090ES TCAS RA)";
937 else if (metype == 29 && (mesub == 0 || mesub == 1))
938 mename = "Target State and Status Message";
939 else if (metype == 31 && (mesub == 0 || mesub == 1))
940 mename = "Aircraft Operational Status Message";
941 return mename;
942 }
943
944 /* Decode a raw Mode S message demodulated as a stream of bytes by
945 * detectModeS(), and split it into fields populating a modesMessage
946 * structure. */
decodeModesMessage(struct modesMessage * mm,unsigned char * msg)947 void decodeModesMessage(struct modesMessage *mm, unsigned char *msg) {
948 uint32_t crc2; /* Computed CRC, used to verify the message CRC. */
949 char *ais_charset = "?ABCDEFGHIJKLMNOPQRSTUVWXYZ????? ???????????????0123456789??????";
950
951 /* Work on our local copy */
952 memcpy(mm->msg,msg,MODES_LONG_MSG_BYTES);
953 msg = mm->msg;
954
955 /* Get the message type ASAP as other operations depend on this */
956 mm->msgtype = msg[0]>>3; /* Downlink Format */
957 mm->msgbits = modesMessageLenByType(mm->msgtype);
958
959 /* CRC is always the last three bytes. */
960 mm->crc = ((uint32_t)msg[(mm->msgbits/8)-3] << 16) |
961 ((uint32_t)msg[(mm->msgbits/8)-2] << 8) |
962 (uint32_t)msg[(mm->msgbits/8)-1];
963 crc2 = modesChecksum(msg,mm->msgbits);
964
965 /* Check CRC and fix single bit errors using the CRC when
966 * possible (DF 11 and 17). */
967 mm->errorbit = -1; /* No error */
968 mm->crcok = (mm->crc == crc2);
969
970 if (!mm->crcok && Modes.fix_errors &&
971 (mm->msgtype == 11 || mm->msgtype == 17))
972 {
973 if ((mm->errorbit = fixSingleBitErrors(msg,mm->msgbits)) != -1) {
974 mm->crc = modesChecksum(msg,mm->msgbits);
975 mm->crcok = 1;
976 } else if (Modes.aggressive && mm->msgtype == 17 &&
977 (mm->errorbit = fixTwoBitsErrors(msg,mm->msgbits)) != -1)
978 {
979 mm->crc = modesChecksum(msg,mm->msgbits);
980 mm->crcok = 1;
981 }
982 }
983
984 /* Note that most of the other computation happens *after* we fix
985 * the single bit errors, otherwise we would need to recompute the
986 * fields again. */
987 mm->ca = msg[0] & 7; /* Responder capabilities. */
988
989 /* ICAO address */
990 mm->aa1 = msg[1];
991 mm->aa2 = msg[2];
992 mm->aa3 = msg[3];
993
994 /* DF 17 type (assuming this is a DF17, otherwise not used) */
995 mm->metype = msg[4] >> 3; /* Extended squitter message type. */
996 mm->mesub = msg[4] & 7; /* Extended squitter message subtype. */
997
998 /* Fields for DF4,5,20,21 */
999 mm->fs = msg[0] & 7; /* Flight status for DF4,5,20,21 */
1000 mm->dr = msg[1] >> 3 & 31; /* Request extraction of downlink request. */
1001 mm->um = ((msg[1] & 7)<<3)| /* Request extraction of downlink request. */
1002 msg[2]>>5;
1003
1004 /* In the squawk (identity) field bits are interleaved like that
1005 * (message bit 20 to bit 32):
1006 *
1007 * C1-A1-C2-A2-C4-A4-ZERO-B1-D1-B2-D2-B4-D4
1008 *
1009 * So every group of three bits A, B, C, D represent an integer
1010 * from 0 to 7.
1011 *
1012 * The actual meaning is just 4 octal numbers, but we convert it
1013 * into a base ten number tha happens to represent the four
1014 * octal numbers.
1015 *
1016 * For more info: http://en.wikipedia.org/wiki/Gillham_code */
1017 {
1018 int a,b,c,d;
1019
1020 a = ((msg[3] & 0x80) >> 5) |
1021 ((msg[2] & 0x02) >> 0) |
1022 ((msg[2] & 0x08) >> 3);
1023 b = ((msg[3] & 0x02) << 1) |
1024 ((msg[3] & 0x08) >> 2) |
1025 ((msg[3] & 0x20) >> 5);
1026 c = ((msg[2] & 0x01) << 2) |
1027 ((msg[2] & 0x04) >> 1) |
1028 ((msg[2] & 0x10) >> 4);
1029 d = ((msg[3] & 0x01) << 2) |
1030 ((msg[3] & 0x04) >> 1) |
1031 ((msg[3] & 0x10) >> 4);
1032 mm->identity = a*1000 + b*100 + c*10 + d;
1033 }
1034
1035 /* DF 11 & 17: try to populate our ICAO addresses whitelist.
1036 * DFs with an AP field (xored addr and crc), try to decode it. */
1037 if (mm->msgtype != 11 && mm->msgtype != 17) {
1038 /* Check if we can check the checksum for the Downlink Formats where
1039 * the checksum is xored with the aircraft ICAO address. We try to
1040 * brute force it using a list of recently seen aircraft addresses. */
1041 if (bruteForceAP(msg,mm)) {
1042 /* We recovered the message, mark the checksum as valid. */
1043 mm->crcok = 1;
1044 } else {
1045 mm->crcok = 0;
1046 }
1047 } else {
1048 /* If this is DF 11 or DF 17 and the checksum was ok,
1049 * we can add this address to the list of recently seen
1050 * addresses. */
1051 if (mm->crcok && mm->errorbit == -1) {
1052 uint32_t addr = (mm->aa1 << 16) | (mm->aa2 << 8) | mm->aa3;
1053 addRecentlySeenICAOAddr(addr);
1054 }
1055 }
1056
1057 /* Decode 13 bit altitude for DF0, DF4, DF16, DF20 */
1058 if (mm->msgtype == 0 || mm->msgtype == 4 ||
1059 mm->msgtype == 16 || mm->msgtype == 20) {
1060 mm->altitude = decodeAC13Field(msg, &mm->unit);
1061 }
1062
1063 /* Decode extended squitter specific stuff. */
1064 if (mm->msgtype == 17) {
1065 /* Decode the extended squitter message. */
1066
1067 if (mm->metype >= 1 && mm->metype <= 4) {
1068 /* Aircraft Identification and Category */
1069 mm->aircraft_type = mm->metype-1;
1070 mm->flight[0] = ais_charset[msg[5]>>2];
1071 mm->flight[1] = ais_charset[((msg[5]&3)<<4)|(msg[6]>>4)];
1072 mm->flight[2] = ais_charset[((msg[6]&15)<<2)|(msg[7]>>6)];
1073 mm->flight[3] = ais_charset[msg[7]&63];
1074 mm->flight[4] = ais_charset[msg[8]>>2];
1075 mm->flight[5] = ais_charset[((msg[8]&3)<<4)|(msg[9]>>4)];
1076 mm->flight[6] = ais_charset[((msg[9]&15)<<2)|(msg[10]>>6)];
1077 mm->flight[7] = ais_charset[msg[10]&63];
1078 mm->flight[8] = '\0';
1079 } else if (mm->metype >= 9 && mm->metype <= 18) {
1080 /* Airborne position Message */
1081 mm->fflag = msg[6] & (1<<2);
1082 mm->tflag = msg[6] & (1<<3);
1083 mm->altitude = decodeAC12Field(msg,&mm->unit);
1084 mm->raw_latitude = ((msg[6] & 3) << 15) |
1085 (msg[7] << 7) |
1086 (msg[8] >> 1);
1087 mm->raw_longitude = ((msg[8]&1) << 16) |
1088 (msg[9] << 8) |
1089 msg[10];
1090 } else if (mm->metype == 19 && mm->mesub >= 1 && mm->mesub <= 4) {
1091 /* Airborne Velocity Message */
1092 if (mm->mesub == 1 || mm->mesub == 2) {
1093 mm->ew_dir = (msg[5]&4) >> 2;
1094 mm->ew_velocity = ((msg[5]&3) << 8) | msg[6];
1095 mm->ns_dir = (msg[7]&0x80) >> 7;
1096 mm->ns_velocity = ((msg[7]&0x7f) << 3) | ((msg[8]&0xe0) >> 5);
1097 mm->vert_rate_source = (msg[8]&0x10) >> 4;
1098 mm->vert_rate_sign = (msg[8]&0x8) >> 3;
1099 mm->vert_rate = ((msg[8]&7) << 6) | ((msg[9]&0xfc) >> 2);
1100 /* Compute velocity and angle from the two speed
1101 * components. */
1102 mm->velocity = sqrt(mm->ns_velocity*mm->ns_velocity+
1103 mm->ew_velocity*mm->ew_velocity);
1104 if (mm->velocity) {
1105 int ewv = mm->ew_velocity;
1106 int nsv = mm->ns_velocity;
1107 double heading;
1108
1109 if (mm->ew_dir) ewv *= -1;
1110 if (mm->ns_dir) nsv *= -1;
1111 heading = atan2(ewv,nsv);
1112
1113 /* Convert to degrees. */
1114 mm->heading = heading * 360 / (M_PI*2);
1115 /* We don't want negative values but a 0-360 scale. */
1116 if (mm->heading < 0) mm->heading += 360;
1117 } else {
1118 mm->heading = 0;
1119 }
1120 } else if (mm->mesub == 3 || mm->mesub == 4) {
1121 mm->heading_is_valid = msg[5] & (1<<2);
1122 mm->heading = (360.0/128) * (((msg[5] & 3) << 5) |
1123 (msg[6] >> 3));
1124 }
1125 }
1126 }
1127 mm->phase_corrected = 0; /* Set to 1 by the caller if needed. */
1128 }
1129
1130 /* This function gets a decoded Mode S Message and prints it on the screen
1131 * in a human readable format. */
displayModesMessage(struct modesMessage * mm)1132 void displayModesMessage(struct modesMessage *mm) {
1133 int j;
1134
1135 /* Handle only addresses mode first. */
1136 if (Modes.onlyaddr) {
1137 printf("%02x%02x%02x\n", mm->aa1, mm->aa2, mm->aa3);
1138 return;
1139 }
1140
1141 /* Show the raw message. */
1142 printf("*");
1143 for (j = 0; j < mm->msgbits/8; j++) printf("%02x", mm->msg[j]);
1144 printf(";\n");
1145
1146 if (Modes.raw) {
1147 fflush(stdout); /* Provide data to the reader ASAP. */
1148 return; /* Enough for --raw mode */
1149 }
1150
1151 printf("CRC: %06x (%s)\n", (int)mm->crc, mm->crcok ? "ok" : "wrong");
1152 if (mm->errorbit != -1)
1153 printf("Single bit error fixed, bit %d\n", mm->errorbit);
1154
1155 if (mm->msgtype == 0) {
1156 /* DF 0 */
1157 printf("DF 0: Short Air-Air Surveillance.\n");
1158 printf(" Altitude : %d %s\n", mm->altitude,
1159 (mm->unit == MODES_UNIT_METERS) ? "meters" : "feet");
1160 printf(" ICAO Address : %02x%02x%02x\n", mm->aa1, mm->aa2, mm->aa3);
1161 } else if (mm->msgtype == 4 || mm->msgtype == 20) {
1162 printf("DF %d: %s, Altitude Reply.\n", mm->msgtype,
1163 (mm->msgtype == 4) ? "Surveillance" : "Comm-B");
1164 printf(" Flight Status : %s\n", fs_str[mm->fs]);
1165 printf(" DR : %d\n", mm->dr);
1166 printf(" UM : %d\n", mm->um);
1167 printf(" Altitude : %d %s\n", mm->altitude,
1168 (mm->unit == MODES_UNIT_METERS) ? "meters" : "feet");
1169 printf(" ICAO Address : %02x%02x%02x\n", mm->aa1, mm->aa2, mm->aa3);
1170
1171 if (mm->msgtype == 20) {
1172 /* TODO: 56 bits DF20 MB additional field. */
1173 }
1174 } else if (mm->msgtype == 5 || mm->msgtype == 21) {
1175 printf("DF %d: %s, Identity Reply.\n", mm->msgtype,
1176 (mm->msgtype == 5) ? "Surveillance" : "Comm-B");
1177 printf(" Flight Status : %s\n", fs_str[mm->fs]);
1178 printf(" DR : %d\n", mm->dr);
1179 printf(" UM : %d\n", mm->um);
1180 printf(" Squawk : %d\n", mm->identity);
1181 printf(" ICAO Address : %02x%02x%02x\n", mm->aa1, mm->aa2, mm->aa3);
1182
1183 if (mm->msgtype == 21) {
1184 /* TODO: 56 bits DF21 MB additional field. */
1185 }
1186 } else if (mm->msgtype == 11) {
1187 /* DF 11 */
1188 printf("DF 11: All Call Reply.\n");
1189 printf(" Capability : %s\n", ca_str[mm->ca]);
1190 printf(" ICAO Address: %02x%02x%02x\n", mm->aa1, mm->aa2, mm->aa3);
1191 } else if (mm->msgtype == 17) {
1192 /* DF 17 */
1193 printf("DF 17: ADS-B message.\n");
1194 printf(" Capability : %d (%s)\n", mm->ca, ca_str[mm->ca]);
1195 printf(" ICAO Address : %02x%02x%02x\n", mm->aa1, mm->aa2, mm->aa3);
1196 printf(" Extended Squitter Type: %d\n", mm->metype);
1197 printf(" Extended Squitter Sub : %d\n", mm->mesub);
1198 printf(" Extended Squitter Name: %s\n",
1199 getMEDescription(mm->metype,mm->mesub));
1200
1201 /* Decode the extended squitter message. */
1202 if (mm->metype >= 1 && mm->metype <= 4) {
1203 /* Aircraft identification. */
1204 char *ac_type_str[4] = {
1205 "Aircraft Type D",
1206 "Aircraft Type C",
1207 "Aircraft Type B",
1208 "Aircraft Type A"
1209 };
1210
1211 printf(" Aircraft Type : %s\n", ac_type_str[mm->aircraft_type]);
1212 printf(" Identification : %s\n", mm->flight);
1213 } else if (mm->metype >= 9 && mm->metype <= 18) {
1214 printf(" F flag : %s\n", mm->fflag ? "odd" : "even");
1215 printf(" T flag : %s\n", mm->tflag ? "UTC" : "non-UTC");
1216 printf(" Altitude : %d feet\n", mm->altitude);
1217 printf(" Latitude : %d (not decoded)\n", mm->raw_latitude);
1218 printf(" Longitude: %d (not decoded)\n", mm->raw_longitude);
1219 } else if (mm->metype == 19 && mm->mesub >= 1 && mm->mesub <= 4) {
1220 if (mm->mesub == 1 || mm->mesub == 2) {
1221 /* Velocity */
1222 printf(" EW direction : %d\n", mm->ew_dir);
1223 printf(" EW velocity : %d\n", mm->ew_velocity);
1224 printf(" NS direction : %d\n", mm->ns_dir);
1225 printf(" NS velocity : %d\n", mm->ns_velocity);
1226 printf(" Vertical rate src : %d\n", mm->vert_rate_source);
1227 printf(" Vertical rate sign: %d\n", mm->vert_rate_sign);
1228 printf(" Vertical rate : %d\n", mm->vert_rate);
1229 } else if (mm->mesub == 3 || mm->mesub == 4) {
1230 printf(" Heading status: %d", mm->heading_is_valid);
1231 printf(" Heading: %d", mm->heading);
1232 }
1233 } else {
1234 printf(" Unrecognized ME type: %d subtype: %d\n",
1235 mm->metype, mm->mesub);
1236 }
1237 } else {
1238 if (Modes.check_crc)
1239 printf("DF %d with good CRC received "
1240 "(decoding still not implemented).\n",
1241 mm->msgtype);
1242 }
1243 }
1244
1245 /* Turn I/Q samples pointed by Modes.data into the magnitude vector
1246 * pointed by Modes.magnitude. */
computeMagnitudeVector(void)1247 void computeMagnitudeVector(void) {
1248 uint16_t *m = Modes.magnitude;
1249 unsigned char *p = Modes.data;
1250 uint32_t j;
1251
1252 /* Compute the magnitudo vector. It's just SQRT(I^2 + Q^2), but
1253 * we rescale to the 0-255 range to exploit the full resolution. */
1254 for (j = 0; j < Modes.data_len; j += 2) {
1255 int i = p[j]-127;
1256 int q = p[j+1]-127;
1257
1258 if (i < 0) i = -i;
1259 if (q < 0) q = -q;
1260 m[j/2] = Modes.maglut[i*129+q];
1261 }
1262 }
1263
1264 /* Return -1 if the message is out of fase left-side
1265 * Return 1 if the message is out of fase right-size
1266 * Return 0 if the message is not particularly out of phase.
1267 *
1268 * Note: this function will access m[-1], so the caller should make sure to
1269 * call it only if we are not at the start of the current buffer. */
detectOutOfPhase(uint16_t * m)1270 int detectOutOfPhase(uint16_t *m) {
1271 if (m[3] > m[2]/3) return 1;
1272 if (m[10] > m[9]/3) return 1;
1273 if (m[6] > m[7]/3) return -1;
1274 if (m[-1] > m[1]/3) return -1;
1275 return 0;
1276 }
1277
1278 /* This function does not really correct the phase of the message, it just
1279 * applies a transformation to the first sample representing a given bit:
1280 *
1281 * If the previous bit was one, we amplify it a bit.
1282 * If the previous bit was zero, we decrease it a bit.
1283 *
1284 * This simple transformation makes the message a bit more likely to be
1285 * correctly decoded for out of phase messages:
1286 *
1287 * When messages are out of phase there is more uncertainty in
1288 * sequences of the same bit multiple times, since 11111 will be
1289 * transmitted as continuously altering magnitude (high, low, high, low...)
1290 *
1291 * However because the message is out of phase some part of the high
1292 * is mixed in the low part, so that it is hard to distinguish if it is
1293 * a zero or a one.
1294 *
1295 * However when the message is out of phase passing from 0 to 1 or from
1296 * 1 to 0 happens in a very recognizable way, for instance in the 0 -> 1
1297 * transition, magnitude goes low, high, high, low, and one of of the
1298 * two middle samples the high will be *very* high as part of the previous
1299 * or next high signal will be mixed there.
1300 *
1301 * Applying our simple transformation we make more likely if the current
1302 * bit is a zero, to detect another zero. Symmetrically if it is a one
1303 * it will be more likely to detect a one because of the transformation.
1304 * In this way similar levels will be interpreted more likely in the
1305 * correct way. */
applyPhaseCorrection(uint16_t * m)1306 void applyPhaseCorrection(uint16_t *m) {
1307 int j;
1308
1309 m += 16; /* Skip preamble. */
1310 for (j = 0; j < (MODES_LONG_MSG_BITS-1)*2; j += 2) {
1311 if (m[j] > m[j+1]) {
1312 /* One */
1313 m[j+2] = (m[j+2] * 5) / 4;
1314 } else {
1315 /* Zero */
1316 m[j+2] = (m[j+2] * 4) / 5;
1317 }
1318 }
1319 }
1320
1321 /* Detect a Mode S messages inside the magnitude buffer pointed by 'm' and of
1322 * size 'mlen' bytes. Every detected Mode S message is convert it into a
1323 * stream of bits and passed to the function to display it. */
detectModeS(uint16_t * m,uint32_t mlen)1324 void detectModeS(uint16_t *m, uint32_t mlen) {
1325 unsigned char bits[MODES_LONG_MSG_BITS];
1326 unsigned char msg[MODES_LONG_MSG_BITS/2];
1327 uint16_t aux[MODES_LONG_MSG_BITS*2];
1328 uint32_t j;
1329 int use_correction = 0;
1330
1331 /* The Mode S preamble is made of impulses of 0.5 microseconds at
1332 * the following time offsets:
1333 *
1334 * 0 - 0.5 usec: first impulse.
1335 * 1.0 - 1.5 usec: second impulse.
1336 * 3.5 - 4 usec: third impulse.
1337 * 4.5 - 5 usec: last impulse.
1338 *
1339 * Since we are sampling at 2 Mhz every sample in our magnitude vector
1340 * is 0.5 usec, so the preamble will look like this, assuming there is
1341 * an impulse at offset 0 in the array:
1342 *
1343 * 0 -----------------
1344 * 1 -
1345 * 2 ------------------
1346 * 3 --
1347 * 4 -
1348 * 5 --
1349 * 6 -
1350 * 7 ------------------
1351 * 8 --
1352 * 9 -------------------
1353 */
1354 for (j = 0; j < mlen - MODES_FULL_LEN*2; j++) {
1355 int low, high, delta, i, errors;
1356 int good_message = 0;
1357
1358 if (use_correction) goto good_preamble; /* We already checked it. */
1359
1360 /* First check of relations between the first 10 samples
1361 * representing a valid preamble. We don't even investigate further
1362 * if this simple test is not passed. */
1363 if (!(m[j] > m[j+1] &&
1364 m[j+1] < m[j+2] &&
1365 m[j+2] > m[j+3] &&
1366 m[j+3] < m[j] &&
1367 m[j+4] < m[j] &&
1368 m[j+5] < m[j] &&
1369 m[j+6] < m[j] &&
1370 m[j+7] > m[j+8] &&
1371 m[j+8] < m[j+9] &&
1372 m[j+9] > m[j+6]))
1373 {
1374 if (Modes.debug & MODES_DEBUG_NOPREAMBLE &&
1375 m[j] > MODES_DEBUG_NOPREAMBLE_LEVEL)
1376 dumpRawMessage("Unexpected ratio among first 10 samples",
1377 msg, m, j);
1378 continue;
1379 }
1380
1381 /* The samples between the two spikes must be < than the average
1382 * of the high spikes level. We don't test bits too near to
1383 * the high levels as signals can be out of phase so part of the
1384 * energy can be in the near samples. */
1385 high = (m[j]+m[j+2]+m[j+7]+m[j+9])/6;
1386 if (m[j+4] >= high ||
1387 m[j+5] >= high)
1388 {
1389 if (Modes.debug & MODES_DEBUG_NOPREAMBLE &&
1390 m[j] > MODES_DEBUG_NOPREAMBLE_LEVEL)
1391 dumpRawMessage(
1392 "Too high level in samples between 3 and 6",
1393 msg, m, j);
1394 continue;
1395 }
1396
1397 /* Similarly samples in the range 11-14 must be low, as it is the
1398 * space between the preamble and real data. Again we don't test
1399 * bits too near to high levels, see above. */
1400 if (m[j+11] >= high ||
1401 m[j+12] >= high ||
1402 m[j+13] >= high ||
1403 m[j+14] >= high)
1404 {
1405 if (Modes.debug & MODES_DEBUG_NOPREAMBLE &&
1406 m[j] > MODES_DEBUG_NOPREAMBLE_LEVEL)
1407 dumpRawMessage(
1408 "Too high level in samples between 10 and 15",
1409 msg, m, j);
1410 continue;
1411 }
1412 Modes.stat_valid_preamble++;
1413
1414 good_preamble:
1415 /* If the previous attempt with this message failed, retry using
1416 * magnitude correction. */
1417 if (use_correction) {
1418 memcpy(aux,m+j+MODES_PREAMBLE_US*2,sizeof(aux));
1419 if (j && detectOutOfPhase(m+j)) {
1420 applyPhaseCorrection(m+j);
1421 Modes.stat_out_of_phase++;
1422 }
1423 /* TODO ... apply other kind of corrections. */
1424 }
1425
1426 /* Decode all the next 112 bits, regardless of the actual message
1427 * size. We'll check the actual message type later. */
1428 errors = 0;
1429 for (i = 0; i < MODES_LONG_MSG_BITS*2; i += 2) {
1430 low = m[j+i+MODES_PREAMBLE_US*2];
1431 high = m[j+i+MODES_PREAMBLE_US*2+1];
1432 delta = low-high;
1433 if (delta < 0) delta = -delta;
1434
1435 if (i > 0 && delta < 256) {
1436 bits[i/2] = bits[i/2-1];
1437 } else if (low == high) {
1438 /* Checking if two adiacent samples have the same magnitude
1439 * is an effective way to detect if it's just random noise
1440 * that was detected as a valid preamble. */
1441 bits[i/2] = 2; /* error */
1442 if (i < MODES_SHORT_MSG_BITS*2) errors++;
1443 } else if (low > high) {
1444 bits[i/2] = 1;
1445 } else {
1446 /* (low < high) for exclusion */
1447 bits[i/2] = 0;
1448 }
1449 }
1450
1451 /* Restore the original message if we used magnitude correction. */
1452 if (use_correction)
1453 memcpy(m+j+MODES_PREAMBLE_US*2,aux,sizeof(aux));
1454
1455 /* Pack bits into bytes */
1456 for (i = 0; i < MODES_LONG_MSG_BITS; i += 8) {
1457 msg[i/8] =
1458 bits[i]<<7 |
1459 bits[i+1]<<6 |
1460 bits[i+2]<<5 |
1461 bits[i+3]<<4 |
1462 bits[i+4]<<3 |
1463 bits[i+5]<<2 |
1464 bits[i+6]<<1 |
1465 bits[i+7];
1466 }
1467
1468 int msgtype = msg[0]>>3;
1469 int msglen = modesMessageLenByType(msgtype)/8;
1470
1471 /* Last check, high and low bits are different enough in magnitude
1472 * to mark this as real message and not just noise? */
1473 delta = 0;
1474 for (i = 0; i < msglen*8*2; i += 2) {
1475 delta += abs(m[j+i+MODES_PREAMBLE_US*2]-
1476 m[j+i+MODES_PREAMBLE_US*2+1]);
1477 }
1478 delta /= msglen*4;
1479
1480 /* Filter for an average delta of three is small enough to let almost
1481 * every kind of message to pass, but high enough to filter some
1482 * random noise. */
1483 if (delta < 10*255) {
1484 use_correction = 0;
1485 continue;
1486 }
1487
1488 /* If we reached this point, and error is zero, we are very likely
1489 * with a Mode S message in our hands, but it may still be broken
1490 * and CRC may not be correct. This is handled by the next layer. */
1491 if (errors == 0 || (Modes.aggressive && errors < 3)) {
1492 struct modesMessage mm;
1493
1494 /* Decode the received message and update statistics */
1495 decodeModesMessage(&mm,msg);
1496
1497 /* Update statistics. */
1498 if (mm.crcok || use_correction) {
1499 if (errors == 0) Modes.stat_demodulated++;
1500 if (mm.errorbit == -1) {
1501 if (mm.crcok)
1502 Modes.stat_goodcrc++;
1503 else
1504 Modes.stat_badcrc++;
1505 } else {
1506 Modes.stat_badcrc++;
1507 Modes.stat_fixed++;
1508 if (mm.errorbit < MODES_LONG_MSG_BITS)
1509 Modes.stat_single_bit_fix++;
1510 else
1511 Modes.stat_two_bits_fix++;
1512 }
1513 }
1514
1515 /* Output debug mode info if needed. */
1516 if (use_correction == 0) {
1517 if (Modes.debug & MODES_DEBUG_DEMOD)
1518 dumpRawMessage("Demodulated with 0 errors", msg, m, j);
1519 else if (Modes.debug & MODES_DEBUG_BADCRC &&
1520 mm.msgtype == 17 &&
1521 (!mm.crcok || mm.errorbit != -1))
1522 dumpRawMessage("Decoded with bad CRC", msg, m, j);
1523 else if (Modes.debug & MODES_DEBUG_GOODCRC && mm.crcok &&
1524 mm.errorbit == -1)
1525 dumpRawMessage("Decoded with good CRC", msg, m, j);
1526 }
1527
1528 /* Skip this message if we are sure it's fine. */
1529 if (mm.crcok) {
1530 j += (MODES_PREAMBLE_US+(msglen*8))*2;
1531 good_message = 1;
1532 if (use_correction)
1533 mm.phase_corrected = 1;
1534 }
1535
1536 /* Pass data to the next layer */
1537 useModesMessage(&mm);
1538 } else {
1539 if (Modes.debug & MODES_DEBUG_DEMODERR && use_correction) {
1540 printf("The following message has %d demod errors\n", errors);
1541 dumpRawMessage("Demodulated with errors", msg, m, j);
1542 }
1543 }
1544
1545 /* Retry with phase correction if possible. */
1546 if (!good_message && !use_correction) {
1547 j--;
1548 use_correction = 1;
1549 } else {
1550 use_correction = 0;
1551 }
1552 }
1553 }
1554
1555 /* When a new message is available, because it was decoded from the
1556 * RTL device, file, or received in the TCP input port, or any other
1557 * way we can receive a decoded message, we call this function in order
1558 * to use the message.
1559 *
1560 * Basically this function passes a raw message to the upper layers for
1561 * further processing and visualization. */
useModesMessage(struct modesMessage * mm)1562 void useModesMessage(struct modesMessage *mm) {
1563 if (!Modes.stats && (Modes.check_crc == 0 || mm->crcok)) {
1564 /* Track aircrafts in interactive mode or if the HTTP
1565 * interface is enabled. */
1566 if (Modes.interactive || Modes.stat_http_requests > 0 || Modes.stat_sbs_connections > 0) {
1567 struct aircraft *a = interactiveReceiveData(mm);
1568 if (a && Modes.stat_sbs_connections > 0) modesSendSBSOutput(mm, a); /* Feed SBS output clients. */
1569 }
1570 /* In non-interactive way, display messages on standard output. */
1571 if (!Modes.interactive) {
1572 displayModesMessage(mm);
1573 if (!Modes.raw && !Modes.onlyaddr) printf("\n");
1574 }
1575 /* Send data to connected clients. */
1576 if (Modes.net) {
1577 modesSendRawOutput(mm); /* Feed raw output clients. */
1578 }
1579 }
1580 }
1581
1582 /* ========================= Interactive mode =============================== */
1583
1584 /* Return a new aircraft structure for the interactive mode linked list
1585 * of aircrafts. */
interactiveCreateAircraft(uint32_t addr)1586 struct aircraft *interactiveCreateAircraft(uint32_t addr) {
1587 struct aircraft *a = malloc(sizeof(*a));
1588
1589 a->addr = addr;
1590 snprintf(a->hexaddr,sizeof(a->hexaddr),"%06x",(int)addr);
1591 a->flight[0] = '\0';
1592 a->altitude = 0;
1593 a->speed = 0;
1594 a->track = 0;
1595 a->odd_cprlat = 0;
1596 a->odd_cprlon = 0;
1597 a->odd_cprtime = 0;
1598 a->even_cprlat = 0;
1599 a->even_cprlon = 0;
1600 a->even_cprtime = 0;
1601 a->lat = 0;
1602 a->lon = 0;
1603 a->seen = time(NULL);
1604 a->messages = 0;
1605 a->next = NULL;
1606 return a;
1607 }
1608
1609 /* Return the aircraft with the specified address, or NULL if no aircraft
1610 * exists with this address. */
interactiveFindAircraft(uint32_t addr)1611 struct aircraft *interactiveFindAircraft(uint32_t addr) {
1612 struct aircraft *a = Modes.aircrafts;
1613
1614 while(a) {
1615 if (a->addr == addr) return a;
1616 a = a->next;
1617 }
1618 return NULL;
1619 }
1620
1621 /* Always positive MOD operation, used for CPR decoding. */
cprModFunction(int a,int b)1622 int cprModFunction(int a, int b) {
1623 int res = a % b;
1624 if (res < 0) res += b;
1625 return res;
1626 }
1627
1628 /* The NL function uses the precomputed table from 1090-WP-9-14 */
cprNLFunction(double lat)1629 int cprNLFunction(double lat) {
1630 if (lat < 0) lat = -lat; /* Table is simmetric about the equator. */
1631 if (lat < 10.47047130) return 59;
1632 if (lat < 14.82817437) return 58;
1633 if (lat < 18.18626357) return 57;
1634 if (lat < 21.02939493) return 56;
1635 if (lat < 23.54504487) return 55;
1636 if (lat < 25.82924707) return 54;
1637 if (lat < 27.93898710) return 53;
1638 if (lat < 29.91135686) return 52;
1639 if (lat < 31.77209708) return 51;
1640 if (lat < 33.53993436) return 50;
1641 if (lat < 35.22899598) return 49;
1642 if (lat < 36.85025108) return 48;
1643 if (lat < 38.41241892) return 47;
1644 if (lat < 39.92256684) return 46;
1645 if (lat < 41.38651832) return 45;
1646 if (lat < 42.80914012) return 44;
1647 if (lat < 44.19454951) return 43;
1648 if (lat < 45.54626723) return 42;
1649 if (lat < 46.86733252) return 41;
1650 if (lat < 48.16039128) return 40;
1651 if (lat < 49.42776439) return 39;
1652 if (lat < 50.67150166) return 38;
1653 if (lat < 51.89342469) return 37;
1654 if (lat < 53.09516153) return 36;
1655 if (lat < 54.27817472) return 35;
1656 if (lat < 55.44378444) return 34;
1657 if (lat < 56.59318756) return 33;
1658 if (lat < 57.72747354) return 32;
1659 if (lat < 58.84763776) return 31;
1660 if (lat < 59.95459277) return 30;
1661 if (lat < 61.04917774) return 29;
1662 if (lat < 62.13216659) return 28;
1663 if (lat < 63.20427479) return 27;
1664 if (lat < 64.26616523) return 26;
1665 if (lat < 65.31845310) return 25;
1666 if (lat < 66.36171008) return 24;
1667 if (lat < 67.39646774) return 23;
1668 if (lat < 68.42322022) return 22;
1669 if (lat < 69.44242631) return 21;
1670 if (lat < 70.45451075) return 20;
1671 if (lat < 71.45986473) return 19;
1672 if (lat < 72.45884545) return 18;
1673 if (lat < 73.45177442) return 17;
1674 if (lat < 74.43893416) return 16;
1675 if (lat < 75.42056257) return 15;
1676 if (lat < 76.39684391) return 14;
1677 if (lat < 77.36789461) return 13;
1678 if (lat < 78.33374083) return 12;
1679 if (lat < 79.29428225) return 11;
1680 if (lat < 80.24923213) return 10;
1681 if (lat < 81.19801349) return 9;
1682 if (lat < 82.13956981) return 8;
1683 if (lat < 83.07199445) return 7;
1684 if (lat < 83.99173563) return 6;
1685 if (lat < 84.89166191) return 5;
1686 if (lat < 85.75541621) return 4;
1687 if (lat < 86.53536998) return 3;
1688 if (lat < 87.00000000) return 2;
1689 else return 1;
1690 }
1691
cprNFunction(double lat,int isodd)1692 int cprNFunction(double lat, int isodd) {
1693 int nl = cprNLFunction(lat) - isodd;
1694 if (nl < 1) nl = 1;
1695 return nl;
1696 }
1697
cprDlonFunction(double lat,int isodd)1698 double cprDlonFunction(double lat, int isodd) {
1699 return 360.0 / cprNFunction(lat, isodd);
1700 }
1701
1702 /* This algorithm comes from:
1703 * http://www.lll.lu/~edward/edward/adsb/DecodingADSBposition.html.
1704 *
1705 *
1706 * A few remarks:
1707 * 1) 131072 is 2^17 since CPR latitude and longitude are encoded in 17 bits.
1708 * 2) We assume that we always received the odd packet as last packet for
1709 * simplicity. This may provide a position that is less fresh of a few
1710 * seconds.
1711 */
decodeCPR(struct aircraft * a)1712 void decodeCPR(struct aircraft *a) {
1713 const double AirDlat0 = 360.0 / 60;
1714 const double AirDlat1 = 360.0 / 59;
1715 double lat0 = a->even_cprlat;
1716 double lat1 = a->odd_cprlat;
1717 double lon0 = a->even_cprlon;
1718 double lon1 = a->odd_cprlon;
1719
1720 /* Compute the Latitude Index "j" */
1721 int j = floor(((59*lat0 - 60*lat1) / 131072) + 0.5);
1722 double rlat0 = AirDlat0 * (cprModFunction(j,60) + lat0 / 131072);
1723 double rlat1 = AirDlat1 * (cprModFunction(j,59) + lat1 / 131072);
1724
1725 if (rlat0 >= 270) rlat0 -= 360;
1726 if (rlat1 >= 270) rlat1 -= 360;
1727
1728 /* Check that both are in the same latitude zone, or abort. */
1729 if (cprNLFunction(rlat0) != cprNLFunction(rlat1)) return;
1730
1731 /* Compute ni and the longitude index m */
1732 if (a->even_cprtime > a->odd_cprtime) {
1733 /* Use even packet. */
1734 int ni = cprNFunction(rlat0,0);
1735 int m = floor((((lon0 * (cprNLFunction(rlat0)-1)) -
1736 (lon1 * cprNLFunction(rlat0))) / 131072) + 0.5);
1737 a->lon = cprDlonFunction(rlat0,0) * (cprModFunction(m,ni)+lon0/131072);
1738 a->lat = rlat0;
1739 } else {
1740 /* Use odd packet. */
1741 int ni = cprNFunction(rlat1,1);
1742 int m = floor((((lon0 * (cprNLFunction(rlat1)-1)) -
1743 (lon1 * cprNLFunction(rlat1))) / 131072.0) + 0.5);
1744 a->lon = cprDlonFunction(rlat1,1) * (cprModFunction(m,ni)+lon1/131072);
1745 a->lat = rlat1;
1746 }
1747 if (a->lon > 180) a->lon -= 360;
1748 }
1749
1750 /* Receive new messages and populate the interactive mode with more info. */
interactiveReceiveData(struct modesMessage * mm)1751 struct aircraft *interactiveReceiveData(struct modesMessage *mm) {
1752 uint32_t addr;
1753 struct aircraft *a, *aux;
1754
1755 if (Modes.check_crc && mm->crcok == 0) return NULL;
1756 addr = (mm->aa1 << 16) | (mm->aa2 << 8) | mm->aa3;
1757
1758 /* Loookup our aircraft or create a new one. */
1759 a = interactiveFindAircraft(addr);
1760 if (!a) {
1761 a = interactiveCreateAircraft(addr);
1762 a->next = Modes.aircrafts;
1763 Modes.aircrafts = a;
1764 } else {
1765 /* If it is an already known aircraft, move it on head
1766 * so we keep aircrafts ordered by received message time.
1767 *
1768 * However move it on head only if at least one second elapsed
1769 * since the aircraft that is currently on head sent a message,
1770 * othewise with multiple aircrafts at the same time we have an
1771 * useless shuffle of positions on the screen. */
1772 if (0 && Modes.aircrafts != a && (time(NULL) - a->seen) >= 1) {
1773 aux = Modes.aircrafts;
1774 while(aux->next != a) aux = aux->next;
1775 /* Now we are a node before the aircraft to remove. */
1776 aux->next = aux->next->next; /* removed. */
1777 /* Add on head */
1778 a->next = Modes.aircrafts;
1779 Modes.aircrafts = a;
1780 }
1781 }
1782
1783 a->seen = time(NULL);
1784 a->messages++;
1785
1786 if (mm->msgtype == 0 || mm->msgtype == 4 || mm->msgtype == 20) {
1787 a->altitude = mm->altitude;
1788 } else if (mm->msgtype == 17) {
1789 if (mm->metype >= 1 && mm->metype <= 4) {
1790 memcpy(a->flight, mm->flight, sizeof(a->flight));
1791 } else if (mm->metype >= 9 && mm->metype <= 18) {
1792 a->altitude = mm->altitude;
1793 if (mm->fflag) {
1794 a->odd_cprlat = mm->raw_latitude;
1795 a->odd_cprlon = mm->raw_longitude;
1796 a->odd_cprtime = mstime();
1797 } else {
1798 a->even_cprlat = mm->raw_latitude;
1799 a->even_cprlon = mm->raw_longitude;
1800 a->even_cprtime = mstime();
1801 }
1802 /* If the two data is less than 10 seconds apart, compute
1803 * the position. */
1804 if (abs(a->even_cprtime - a->odd_cprtime) <= 10000) {
1805 decodeCPR(a);
1806 }
1807 } else if (mm->metype == 19) {
1808 if (mm->mesub == 1 || mm->mesub == 2) {
1809 a->speed = mm->velocity;
1810 a->track = mm->heading;
1811 }
1812 }
1813 }
1814 return a;
1815 }
1816
1817 /* Show the currently captured interactive data on screen. */
interactiveShowData(void)1818 void interactiveShowData(void) {
1819 struct aircraft *a = Modes.aircrafts;
1820 time_t now = time(NULL);
1821 char progress[4];
1822 int count = 0;
1823
1824 memset(progress,' ',3);
1825 progress[time(NULL)%3] = '.';
1826 progress[3] = '\0';
1827
1828 printf("\x1b[H\x1b[2J"); /* Clear the screen */
1829 printf(
1830 "Hex Flight Altitude Speed Lat Lon Track Messages Seen %s\n"
1831 "--------------------------------------------------------------------------------\n",
1832 progress);
1833
1834 while(a && count < Modes.interactive_rows) {
1835 int altitude = a->altitude, speed = a->speed;
1836
1837 /* Convert units to metric if --metric was specified. */
1838 if (Modes.metric) {
1839 altitude /= 3.2828;
1840 speed *= 1.852;
1841 }
1842
1843 printf("%-6s %-8s %-9d %-7d %-7.03f %-7.03f %-3d %-9ld %d sec\n",
1844 a->hexaddr, a->flight, altitude, speed,
1845 a->lat, a->lon, a->track, a->messages,
1846 (int)(now - a->seen));
1847 a = a->next;
1848 count++;
1849 }
1850 }
1851
1852 /* When in interactive mode If we don't receive new nessages within
1853 * MODES_INTERACTIVE_TTL seconds we remove the aircraft from the list. */
interactiveRemoveStaleAircrafts(void)1854 void interactiveRemoveStaleAircrafts(void) {
1855 struct aircraft *a = Modes.aircrafts;
1856 struct aircraft *prev = NULL;
1857 time_t now = time(NULL);
1858
1859 while(a) {
1860 if ((now - a->seen) > Modes.interactive_ttl) {
1861 struct aircraft *next = a->next;
1862 /* Remove the element from the linked list, with care
1863 * if we are removing the first element. */
1864 free(a);
1865 if (!prev)
1866 Modes.aircrafts = next;
1867 else
1868 prev->next = next;
1869 a = next;
1870 } else {
1871 prev = a;
1872 a = a->next;
1873 }
1874 }
1875 }
1876
1877 /* ============================== Snip mode ================================= */
1878
1879 /* Get raw IQ samples and filter everything is < than the specified level
1880 * for more than 256 samples in order to reduce example file size. */
snipMode(int level)1881 void snipMode(int level) {
1882 int i, q;
1883 long long c = 0;
1884
1885 while ((i = getchar()) != EOF && (q = getchar()) != EOF) {
1886 if (abs(i-127) < level && abs(q-127) < level) {
1887 c++;
1888 if (c > MODES_PREAMBLE_US*4) continue;
1889 } else {
1890 c = 0;
1891 }
1892 putchar(i);
1893 putchar(q);
1894 }
1895 }
1896
1897 /* ============================= Networking =================================
1898 * Note: here we risregard any kind of good coding practice in favor of
1899 * extreme simplicity, that is:
1900 *
1901 * 1) We only rely on the kernel buffers for our I/O without any kind of
1902 * user space buffering.
1903 * 2) We don't register any kind of event handler, from time to time a
1904 * function gets called and we accept new connections. All the rest is
1905 * handled via non-blocking I/O and manually pulling clients to see if
1906 * they have something new to share with us when reading is needed.
1907 */
1908
1909 #define MODES_NET_SERVICE_RAWO 0
1910 #define MODES_NET_SERVICE_RAWI 1
1911 #define MODES_NET_SERVICE_HTTP 2
1912 #define MODES_NET_SERVICE_SBS 3
1913 #define MODES_NET_SERVICES_NUM 4
1914 struct {
1915 char *descr;
1916 int *socket;
1917 int port;
1918 } modesNetServices[MODES_NET_SERVICES_NUM] = {
1919 {"Raw TCP output", &Modes.ros, MODES_NET_OUTPUT_RAW_PORT},
1920 {"Raw TCP input", &Modes.ris, MODES_NET_INPUT_RAW_PORT},
1921 {"HTTP server", &Modes.https, MODES_NET_HTTP_PORT},
1922 {"Basestation TCP output", &Modes.sbsos, MODES_NET_OUTPUT_SBS_PORT}
1923 };
1924
1925 /* Networking "stack" initialization. */
modesInitNet(void)1926 void modesInitNet(void) {
1927 int j;
1928
1929 memset(Modes.clients,0,sizeof(Modes.clients));
1930 Modes.maxfd = -1;
1931
1932 for (j = 0; j < MODES_NET_SERVICES_NUM; j++) {
1933 int s = anetTcpServer(Modes.aneterr, modesNetServices[j].port, NULL);
1934 if (s == -1) {
1935 fprintf(stderr, "Error opening the listening port %d (%s): %s\n",
1936 modesNetServices[j].port,
1937 modesNetServices[j].descr,
1938 strerror(errno));
1939 exit(1);
1940 }
1941 anetNonBlock(Modes.aneterr, s);
1942 *modesNetServices[j].socket = s;
1943 }
1944
1945 signal(SIGPIPE, SIG_IGN);
1946 }
1947
1948 /* This function gets called from time to time when the decoding thread is
1949 * awakened by new data arriving. This usually happens a few times every
1950 * second. */
modesAcceptClients(void)1951 void modesAcceptClients(void) {
1952 int fd, port;
1953 unsigned int j;
1954 struct client *c;
1955
1956 for (j = 0; j < MODES_NET_SERVICES_NUM; j++) {
1957 fd = anetTcpAccept(Modes.aneterr, *modesNetServices[j].socket,
1958 NULL, &port);
1959 if (fd == -1) {
1960 if (Modes.debug & MODES_DEBUG_NET && errno != EAGAIN)
1961 printf("Accept %d: %s\n", *modesNetServices[j].socket,
1962 strerror(errno));
1963 continue;
1964 }
1965
1966 if (fd >= MODES_NET_MAX_FD) {
1967 close(fd);
1968 return; /* Max number of clients reached. */
1969 }
1970
1971 anetNonBlock(Modes.aneterr, fd);
1972 c = malloc(sizeof(*c));
1973 c->service = *modesNetServices[j].socket;
1974 c->fd = fd;
1975 c->buflen = 0;
1976 Modes.clients[fd] = c;
1977 anetSetSendBuffer(Modes.aneterr,fd,MODES_NET_SNDBUF_SIZE);
1978
1979 if (Modes.maxfd < fd) Modes.maxfd = fd;
1980 if (*modesNetServices[j].socket == Modes.sbsos)
1981 Modes.stat_sbs_connections++;
1982
1983 j--; /* Try again with the same listening port. */
1984
1985 if (Modes.debug & MODES_DEBUG_NET)
1986 printf("Created new client %d\n", fd);
1987 }
1988 }
1989
1990 /* On error free the client, collect the structure, adjust maxfd if needed. */
modesFreeClient(int fd)1991 void modesFreeClient(int fd) {
1992 close(fd);
1993 free(Modes.clients[fd]);
1994 Modes.clients[fd] = NULL;
1995
1996 if (Modes.debug & MODES_DEBUG_NET)
1997 printf("Closing client %d\n", fd);
1998
1999 /* If this was our maxfd, scan the clients array to find the new max.
2000 * Note that we are sure there is no active fd greater than the closed
2001 * fd, so we scan from fd-1 to 0. */
2002 if (Modes.maxfd == fd) {
2003 int j;
2004
2005 Modes.maxfd = -1;
2006 for (j = fd-1; j >= 0; j--) {
2007 if (Modes.clients[j]) {
2008 Modes.maxfd = j;
2009 break;
2010 }
2011 }
2012 }
2013 }
2014
2015 /* Send the specified message to all clients listening for a given service. */
modesSendAllClients(int service,void * msg,int len)2016 void modesSendAllClients(int service, void *msg, int len) {
2017 int j;
2018 struct client *c;
2019
2020 for (j = 0; j <= Modes.maxfd; j++) {
2021 c = Modes.clients[j];
2022 if (c && c->service == service) {
2023 int nwritten = write(j, msg, len);
2024 if (nwritten != len) {
2025 modesFreeClient(j);
2026 }
2027 }
2028 }
2029 }
2030
2031 /* Write raw output to TCP clients. */
modesSendRawOutput(struct modesMessage * mm)2032 void modesSendRawOutput(struct modesMessage *mm) {
2033 char msg[128], *p = msg;
2034 int j;
2035
2036 *p++ = '*';
2037 for (j = 0; j < mm->msgbits/8; j++) {
2038 sprintf(p, "%02X", mm->msg[j]);
2039 p += 2;
2040 }
2041 *p++ = ';';
2042 *p++ = '\n';
2043 modesSendAllClients(Modes.ros, msg, p-msg);
2044 }
2045
2046
2047 /* Write SBS output to TCP clients. */
modesSendSBSOutput(struct modesMessage * mm,struct aircraft * a)2048 void modesSendSBSOutput(struct modesMessage *mm, struct aircraft *a) {
2049 char msg[256], *p = msg;
2050 int emergency = 0, ground = 0, alert = 0, spi = 0;
2051
2052 if (mm->msgtype == 4 || mm->msgtype == 5 || mm->msgtype == 21) {
2053 /* Node: identity is calculated/kept in base10 but is actually
2054 * octal (07500 is represented as 7500) */
2055 if (mm->identity == 7500 || mm->identity == 7600 ||
2056 mm->identity == 7700) emergency = -1;
2057 if (mm->fs == 1 || mm->fs == 3) ground = -1;
2058 if (mm->fs == 2 || mm->fs == 3 || mm->fs == 4) alert = -1;
2059 if (mm->fs == 4 || mm->fs == 5) spi = -1;
2060 }
2061
2062 if (mm->msgtype == 0) {
2063 p += sprintf(p, "MSG,5,,,%02X%02X%02X,,,,,,,%d,,,,,,,,,,",
2064 mm->aa1, mm->aa2, mm->aa3, mm->altitude);
2065 } else if (mm->msgtype == 4) {
2066 p += sprintf(p, "MSG,5,,,%02X%02X%02X,,,,,,,%d,,,,,,,%d,%d,%d,%d",
2067 mm->aa1, mm->aa2, mm->aa3, mm->altitude, alert, emergency, spi, ground);
2068 } else if (mm->msgtype == 5) {
2069 p += sprintf(p, "MSG,6,,,%02X%02X%02X,,,,,,,,,,,,,%d,%d,%d,%d,%d",
2070 mm->aa1, mm->aa2, mm->aa3, mm->identity, alert, emergency, spi, ground);
2071 } else if (mm->msgtype == 11) {
2072 p += sprintf(p, "MSG,8,,,%02X%02X%02X,,,,,,,,,,,,,,,,,",
2073 mm->aa1, mm->aa2, mm->aa3);
2074 } else if (mm->msgtype == 17 && mm->metype == 4) {
2075 p += sprintf(p, "MSG,1,,,%02X%02X%02X,,,,,,%s,,,,,,,,0,0,0,0",
2076 mm->aa1, mm->aa2, mm->aa3, mm->flight);
2077 } else if (mm->msgtype == 17 && mm->metype >= 9 && mm->metype <= 18) {
2078 if (a->lat == 0 && a->lon == 0)
2079 p += sprintf(p, "MSG,3,,,%02X%02X%02X,,,,,,,%d,,,,,,,0,0,0,0",
2080 mm->aa1, mm->aa2, mm->aa3, mm->altitude);
2081 else
2082 p += sprintf(p, "MSG,3,,,%02X%02X%02X,,,,,,,%d,,,%1.5f,%1.5f,,,"
2083 "0,0,0,0",
2084 mm->aa1, mm->aa2, mm->aa3, mm->altitude, a->lat, a->lon);
2085 } else if (mm->msgtype == 17 && mm->metype == 19 && mm->mesub == 1) {
2086 int vr = (mm->vert_rate_sign==0?1:-1) * (mm->vert_rate-1) * 64;
2087
2088 p += sprintf(p, "MSG,4,,,%02X%02X%02X,,,,,,,,%d,%d,,,%i,,0,0,0,0",
2089 mm->aa1, mm->aa2, mm->aa3, a->speed, a->track, vr);
2090 } else if (mm->msgtype == 21) {
2091 p += sprintf(p, "MSG,6,,,%02X%02X%02X,,,,,,,,,,,,,%d,%d,%d,%d,%d",
2092 mm->aa1, mm->aa2, mm->aa3, mm->identity, alert, emergency, spi, ground);
2093 } else {
2094 return;
2095 }
2096
2097 *p++ = '\n';
2098 modesSendAllClients(Modes.sbsos, msg, p-msg);
2099 }
2100
2101 /* Turn an hex digit into its 4 bit decimal value.
2102 * Returns -1 if the digit is not in the 0-F range. */
hexDigitVal(int c)2103 int hexDigitVal(int c) {
2104 c = tolower(c);
2105 if (c >= '0' && c <= '9') return c-'0';
2106 else if (c >= 'a' && c <= 'f') return c-'a'+10;
2107 else return -1;
2108 }
2109
2110 /* This function decodes a string representing a Mode S message in
2111 * raw hex format like: *8D4B969699155600E87406F5B69F;
2112 * The string is supposed to be at the start of the client buffer
2113 * and null-terminated.
2114 *
2115 * The message is passed to the higher level layers, so it feeds
2116 * the selected screen output, the network output and so forth.
2117 *
2118 * If the message looks invalid is silently discarded.
2119 *
2120 * The function always returns 0 (success) to the caller as there is
2121 * no case where we want broken messages here to close the client
2122 * connection. */
decodeHexMessage(struct client * c)2123 int decodeHexMessage(struct client *c) {
2124 char *hex = c->buf;
2125 int l = strlen(hex), j;
2126 unsigned char msg[MODES_LONG_MSG_BYTES];
2127 struct modesMessage mm;
2128
2129 /* Remove spaces on the left and on the right. */
2130 while(l && isspace(hex[l-1])) {
2131 hex[l-1] = '\0';
2132 l--;
2133 }
2134 while(isspace(*hex)) {
2135 hex++;
2136 l--;
2137 }
2138
2139 /* Turn the message into binary. */
2140 if (l < 2 || hex[0] != '*' || hex[l-1] != ';') return 0;
2141 hex++; l-=2; /* Skip * and ; */
2142 if (l > MODES_LONG_MSG_BYTES*2) return 0; /* Too long message... broken. */
2143 for (j = 0; j < l; j += 2) {
2144 int high = hexDigitVal(hex[j]);
2145 int low = hexDigitVal(hex[j+1]);
2146
2147 if (high == -1 || low == -1) return 0;
2148 msg[j/2] = (high<<4) | low;
2149 }
2150 decodeModesMessage(&mm,msg);
2151 useModesMessage(&mm);
2152 return 0;
2153 }
2154
2155 /* Return a description of planes in json. */
aircraftsToJson(int * len)2156 char *aircraftsToJson(int *len) {
2157 struct aircraft *a = Modes.aircrafts;
2158 int buflen = 1024; /* The initial buffer is incremented as needed. */
2159 char *buf = malloc(buflen), *p = buf;
2160 int l;
2161
2162 l = snprintf(p,buflen,"[\n");
2163 p += l; buflen -= l;
2164 while(a) {
2165 int altitude = a->altitude, speed = a->speed;
2166
2167 /* Convert units to metric if --metric was specified. */
2168 if (Modes.metric) {
2169 altitude /= 3.2828;
2170 speed *= 1.852;
2171 }
2172
2173 if (a->lat != 0 && a->lon != 0) {
2174 l = snprintf(p,buflen,
2175 "{\"hex\":\"%s\", \"flight\":\"%s\", \"lat\":%f, "
2176 "\"lon\":%f, \"altitude\":%d, \"track\":%d, "
2177 "\"speed\":%d},\n",
2178 a->hexaddr, a->flight, a->lat, a->lon, a->altitude, a->track,
2179 a->speed);
2180 p += l; buflen -= l;
2181 /* Resize if needed. */
2182 if (buflen < 256) {
2183 int used = p-buf;
2184 buflen += 1024; /* Our increment. */
2185 buf = realloc(buf,used+buflen);
2186 p = buf+used;
2187 }
2188 }
2189 a = a->next;
2190 }
2191 /* Remove the final comma if any, and closes the json array. */
2192 if (*(p-2) == ',') {
2193 *(p-2) = '\n';
2194 p--;
2195 buflen++;
2196 }
2197 l = snprintf(p,buflen,"]\n");
2198 p += l; buflen -= l;
2199
2200 *len = p-buf;
2201 return buf;
2202 }
2203
2204 #define MODES_CONTENT_TYPE_HTML "text/html;charset=utf-8"
2205 #define MODES_CONTENT_TYPE_JSON "application/json;charset=utf-8"
2206
2207 /* Get an HTTP request header and write the response to the client.
2208 * Again here we assume that the socket buffer is enough without doing
2209 * any kind of userspace buffering.
2210 *
2211 * Returns 1 on error to signal the caller the client connection should
2212 * be closed. */
handleHTTPRequest(struct client * c)2213 int handleHTTPRequest(struct client *c) {
2214 char hdr[512];
2215 int clen, hdrlen;
2216 int httpver, keepalive;
2217 char *p, *url, *content;
2218 char *ctype;
2219
2220 if (Modes.debug & MODES_DEBUG_NET)
2221 printf("\nHTTP request: %s\n", c->buf);
2222
2223 /* Minimally parse the request. */
2224 httpver = (strstr(c->buf, "HTTP/1.1") != NULL) ? 11 : 10;
2225 if (httpver == 10) {
2226 /* HTTP 1.0 defaults to close, unless otherwise specified. */
2227 keepalive = strstr(c->buf, "Connection: keep-alive") != NULL;
2228 } else if (httpver == 11) {
2229 /* HTTP 1.1 defaults to keep-alive, unless close is specified. */
2230 keepalive = strstr(c->buf, "Connection: close") == NULL;
2231 }
2232
2233 /* Identify he URL. */
2234 p = strchr(c->buf,' ');
2235 if (!p) return 1; /* There should be the method and a space... */
2236 url = ++p; /* Now this should point to the requested URL. */
2237 p = strchr(p, ' ');
2238 if (!p) return 1; /* There should be a space before HTTP/... */
2239 *p = '\0';
2240
2241 if (Modes.debug & MODES_DEBUG_NET) {
2242 printf("\nHTTP keep alive: %d\n", keepalive);
2243 printf("HTTP requested URL: %s\n\n", url);
2244 }
2245
2246 /* Select the content to send, we have just two so far:
2247 * "/" -> Our google map application.
2248 * "/data.json" -> Our ajax request to update planes. */
2249 if (strstr(url, "/data.json")) {
2250 content = aircraftsToJson(&clen);
2251 ctype = MODES_CONTENT_TYPE_JSON;
2252 } else {
2253 struct stat sbuf;
2254 int fd = -1;
2255
2256 if (stat("/usr/local/share/dump1090/gmap.html",&sbuf) != -1 &&
2257 (fd = open("/usr/local/share/dump1090/gmap.html",O_RDONLY)) != -1)
2258 {
2259 content = malloc(sbuf.st_size);
2260 if (read(fd,content,sbuf.st_size) == -1) {
2261 snprintf(content,sbuf.st_size,"Error reading from file: %s",
2262 strerror(errno));
2263 }
2264 clen = sbuf.st_size;
2265 } else {
2266 char buf[128];
2267
2268 clen = snprintf(buf,sizeof(buf),"Error opening HTML file: %s",
2269 strerror(errno));
2270 content = strdup(buf);
2271 }
2272 if (fd != -1) close(fd);
2273 ctype = MODES_CONTENT_TYPE_HTML;
2274 }
2275
2276 /* Create the header and send the reply. */
2277 hdrlen = snprintf(hdr, sizeof(hdr),
2278 "HTTP/1.1 200 OK\r\n"
2279 "Server: Dump1090\r\n"
2280 "Content-Type: %s\r\n"
2281 "Connection: %s\r\n"
2282 "Content-Length: %d\r\n"
2283 "Access-Control-Allow-Origin: *\r\n"
2284 "\r\n",
2285 ctype,
2286 keepalive ? "keep-alive" : "close",
2287 clen);
2288
2289 if (Modes.debug & MODES_DEBUG_NET)
2290 printf("HTTP Reply header:\n%s", hdr);
2291
2292 /* Send header and content. */
2293 if (write(c->fd, hdr, hdrlen) != hdrlen ||
2294 write(c->fd, content, clen) != clen)
2295 {
2296 free(content);
2297 return 1;
2298 }
2299 free(content);
2300 Modes.stat_http_requests++;
2301 return !keepalive;
2302 }
2303
2304 /* This function polls the clients using read() in order to receive new
2305 * messages from the net.
2306 *
2307 * The message is supposed to be separated by the next message by the
2308 * separator 'sep', that is a null-terminated C string.
2309 *
2310 * Every full message received is decoded and passed to the higher layers
2311 * calling the function 'handler'.
2312 *
2313 * The handelr returns 0 on success, or 1 to signal this function we
2314 * should close the connection with the client in case of non-recoverable
2315 * errors. */
modesReadFromClient(struct client * c,char * sep,int (* handler)(struct client *))2316 void modesReadFromClient(struct client *c, char *sep,
2317 int(*handler)(struct client *))
2318 {
2319 while(1) {
2320 int left = MODES_CLIENT_BUF_SIZE - c->buflen;
2321 int nread = read(c->fd, c->buf+c->buflen, left);
2322 int fullmsg = 0;
2323 int i;
2324 char *p;
2325
2326 if (nread <= 0) {
2327 if (nread == 0 || errno != EAGAIN) {
2328 /* Error, or end of file. */
2329 modesFreeClient(c->fd);
2330 }
2331 break; /* Serve next client. */
2332 }
2333 c->buflen += nread;
2334
2335 /* Always null-term so we are free to use strstr() */
2336 c->buf[c->buflen] = '\0';
2337
2338 /* If there is a complete message there must be the separator 'sep'
2339 * in the buffer, note that we full-scan the buffer at every read
2340 * for simplicity. */
2341 while ((p = strstr(c->buf, sep)) != NULL) {
2342 i = p - c->buf; /* Turn it as an index inside the buffer. */
2343 c->buf[i] = '\0'; /* Te handler expects null terminated strings. */
2344 /* Call the function to process the message. It returns 1
2345 * on error to signal we should close the client connection. */
2346 if (handler(c)) {
2347 modesFreeClient(c->fd);
2348 return;
2349 }
2350 /* Move what's left at the start of the buffer. */
2351 i += strlen(sep); /* The separator is part of the previous msg. */
2352 memmove(c->buf,c->buf+i,c->buflen-i);
2353 c->buflen -= i;
2354 c->buf[c->buflen] = '\0';
2355 /* Maybe there are more messages inside the buffer.
2356 * Start looping from the start again. */
2357 fullmsg = 1;
2358 }
2359 /* If our buffer is full discard it, this is some badly
2360 * formatted shit. */
2361 if (c->buflen == MODES_CLIENT_BUF_SIZE) {
2362 c->buflen = 0;
2363 /* If there is garbage, read more to discard it ASAP. */
2364 continue;
2365 }
2366 /* If no message was decoded process the next client, otherwise
2367 * read more data from the same client. */
2368 if (!fullmsg) break;
2369 }
2370 }
2371
2372 /* Read data from clients. This function actually delegates a lower-level
2373 * function that depends on the kind of service (raw, http, ...). */
modesReadFromClients(void)2374 void modesReadFromClients(void) {
2375 int j;
2376 struct client *c;
2377
2378 for (j = 0; j <= Modes.maxfd; j++) {
2379 if ((c = Modes.clients[j]) == NULL) continue;
2380 if (c->service == Modes.ris)
2381 modesReadFromClient(c,"\n",decodeHexMessage);
2382 else if (c->service == Modes.https)
2383 modesReadFromClient(c,"\r\n\r\n",handleHTTPRequest);
2384 }
2385 }
2386
2387 /* This function is used when "net only" mode is enabled to know when there
2388 * is at least a new client to serve. Note that the dump1090 networking model
2389 * is extremely trivial and a function takes care of handling all the clients
2390 * that have something to serve, without a proper event library, so the
2391 * function here returns as long as there is a single client ready, or
2392 * when the specified timeout in milliesconds elapsed, without specifying to
2393 * the caller what client requires to be served. */
modesWaitReadableClients(int timeout_ms)2394 void modesWaitReadableClients(int timeout_ms) {
2395 struct timeval tv;
2396 fd_set fds;
2397 int j, maxfd = Modes.maxfd;
2398
2399 FD_ZERO(&fds);
2400
2401 /* Set client FDs */
2402 for (j = 0; j <= Modes.maxfd; j++) {
2403 if (Modes.clients[j]) FD_SET(j,&fds);
2404 }
2405
2406 /* Set listening sockets to accept new clients ASAP. */
2407 for (j = 0; j < MODES_NET_SERVICES_NUM; j++) {
2408 int s = *modesNetServices[j].socket;
2409 FD_SET(s,&fds);
2410 if (s > maxfd) maxfd = s;
2411 }
2412
2413 tv.tv_sec = timeout_ms/1000;
2414 tv.tv_usec = (timeout_ms%1000)*1000;
2415 /* We don't care why select returned here, timeout, error, or
2416 * FDs ready are all conditions for which we just return. */
2417 select(maxfd+1,&fds,NULL,NULL,&tv);
2418 }
2419
2420 /* ============================ Terminal handling ========================== */
2421
2422 /* Handle resizing terminal. */
sigWinchCallback()2423 void sigWinchCallback() {
2424 signal(SIGWINCH, SIG_IGN);
2425 Modes.interactive_rows = getTermRows();
2426 interactiveShowData();
2427 signal(SIGWINCH, sigWinchCallback);
2428 }
2429
2430 /* Get the number of rows after the terminal changes size. */
getTermRows()2431 int getTermRows() {
2432 struct winsize w;
2433 ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
2434 return w.ws_row;
2435 }
2436
2437 /* ================================ Main ==================================== */
2438
showHelp(void)2439 void showHelp(void) {
2440 printf(
2441 "--device-index <index> Select RTL device (default: 0).\n"
2442 "--gain <db> Set gain (default: max gain. Use -100 for auto-gain).\n"
2443 "--enable-agc Enable the Automatic Gain Control (default: off).\n"
2444 "--freq <hz> Set frequency (default: 1090 Mhz).\n"
2445 "--ifile <filename> Read data from file (use '-' for stdin).\n"
2446 "--loop With --ifile, read the same file in a loop.\n"
2447 "--interactive Interactive mode refreshing data on screen.\n"
2448 "--interactive-rows <num> Max number of rows in interactive mode (default: 15).\n"
2449 "--interactive-ttl <sec> Remove from list if idle for <sec> (default: 60).\n"
2450 "--raw Show only messages hex values.\n"
2451 "--net Enable networking.\n"
2452 "--net-only Enable just networking, no RTL device or file used.\n"
2453 "--net-ro-port <port> TCP listening port for raw output (default: 30002).\n"
2454 "--net-ri-port <port> TCP listening port for raw input (default: 30001).\n"
2455 "--net-http-port <port> HTTP server port (default: 8080).\n"
2456 "--net-sbs-port <port> TCP listening port for BaseStation format output (default: 30003).\n"
2457 "--no-fix Disable single-bits error correction using CRC.\n"
2458 "--no-crc-check Disable messages with broken CRC (discouraged).\n"
2459 "--aggressive More CPU for more messages (two bits fixes, ...).\n"
2460 "--stats With --ifile print stats at exit. No other output.\n"
2461 "--onlyaddr Show only ICAO addresses (testing purposes).\n"
2462 "--metric Use metric units (meters, km/h, ...).\n"
2463 "--snip <level> Strip IQ file removing samples < level.\n"
2464 "--debug <flags> Debug mode (verbose), see README for details.\n"
2465 "--help Show this help.\n"
2466 "\n"
2467 "Debug mode flags: d = Log frames decoded with errors\n"
2468 " D = Log frames decoded with zero errors\n"
2469 " c = Log frames with bad CRC\n"
2470 " C = Log frames with good CRC\n"
2471 " p = Log frames with bad preamble\n"
2472 " n = Log network debugging info\n"
2473 " j = Log frames to frames.js, loadable by debug.html.\n"
2474 );
2475 }
2476
2477 /* This function is called a few times every second by main in order to
2478 * perform tasks we need to do continuously, like accepting new clients
2479 * from the net, refreshing the screen in interactive mode, and so forth. */
backgroundTasks(void)2480 void backgroundTasks(void) {
2481 if (Modes.net) {
2482 modesAcceptClients();
2483 modesReadFromClients();
2484 interactiveRemoveStaleAircrafts();
2485 }
2486
2487 /* Refresh screen when in interactive mode. */
2488 if (Modes.interactive &&
2489 (mstime() - Modes.interactive_last_update) >
2490 MODES_INTERACTIVE_REFRESH_TIME)
2491 {
2492 interactiveRemoveStaleAircrafts();
2493 interactiveShowData();
2494 Modes.interactive_last_update = mstime();
2495 }
2496 }
2497
main(int argc,char ** argv)2498 int main(int argc, char **argv) {
2499 int j;
2500
2501 /* Set sane defaults. */
2502 modesInitConfig();
2503
2504 /* Parse the command line options */
2505 for (j = 1; j < argc; j++) {
2506 int more = j+1 < argc; /* There are more arguments. */
2507
2508 if (!strcmp(argv[j],"--device-index") && more) {
2509 Modes.dev_index = atoi(argv[++j]);
2510 } else if (!strcmp(argv[j],"--gain") && more) {
2511 Modes.gain = atof(argv[++j])*10; /* Gain is in tens of DBs */
2512 } else if (!strcmp(argv[j],"--enable-agc")) {
2513 Modes.enable_agc++;
2514 } else if (!strcmp(argv[j],"--freq") && more) {
2515 Modes.freq = strtoll(argv[++j],NULL,10);
2516 } else if (!strcmp(argv[j],"--ifile") && more) {
2517 Modes.filename = strdup(argv[++j]);
2518 } else if (!strcmp(argv[j],"--loop")) {
2519 Modes.loop = 1;
2520 } else if (!strcmp(argv[j],"--no-fix")) {
2521 Modes.fix_errors = 0;
2522 } else if (!strcmp(argv[j],"--no-crc-check")) {
2523 Modes.check_crc = 0;
2524 } else if (!strcmp(argv[j],"--raw")) {
2525 Modes.raw = 1;
2526 } else if (!strcmp(argv[j],"--net")) {
2527 Modes.net = 1;
2528 } else if (!strcmp(argv[j],"--net-only")) {
2529 Modes.net = 1;
2530 Modes.net_only = 1;
2531 } else if (!strcmp(argv[j],"--net-ro-port") && more) {
2532 modesNetServices[MODES_NET_SERVICE_RAWO].port = atoi(argv[++j]);
2533 } else if (!strcmp(argv[j],"--net-ri-port") && more) {
2534 modesNetServices[MODES_NET_SERVICE_RAWI].port = atoi(argv[++j]);
2535 } else if (!strcmp(argv[j],"--net-http-port") && more) {
2536 modesNetServices[MODES_NET_SERVICE_HTTP].port = atoi(argv[++j]);
2537 } else if (!strcmp(argv[j],"--net-sbs-port") && more) {
2538 modesNetServices[MODES_NET_SERVICE_SBS].port = atoi(argv[++j]);
2539 } else if (!strcmp(argv[j],"--onlyaddr")) {
2540 Modes.onlyaddr = 1;
2541 } else if (!strcmp(argv[j],"--metric")) {
2542 Modes.metric = 1;
2543 } else if (!strcmp(argv[j],"--aggressive")) {
2544 Modes.aggressive++;
2545 } else if (!strcmp(argv[j],"--interactive")) {
2546 Modes.interactive = 1;
2547 } else if (!strcmp(argv[j],"--interactive-rows")) {
2548 Modes.interactive_rows = atoi(argv[++j]);
2549 } else if (!strcmp(argv[j],"--interactive-ttl")) {
2550 Modes.interactive_ttl = atoi(argv[++j]);
2551 } else if (!strcmp(argv[j],"--debug") && more) {
2552 char *f = argv[++j];
2553 while(*f) {
2554 switch(*f) {
2555 case 'D': Modes.debug |= MODES_DEBUG_DEMOD; break;
2556 case 'd': Modes.debug |= MODES_DEBUG_DEMODERR; break;
2557 case 'C': Modes.debug |= MODES_DEBUG_GOODCRC; break;
2558 case 'c': Modes.debug |= MODES_DEBUG_BADCRC; break;
2559 case 'p': Modes.debug |= MODES_DEBUG_NOPREAMBLE; break;
2560 case 'n': Modes.debug |= MODES_DEBUG_NET; break;
2561 case 'j': Modes.debug |= MODES_DEBUG_JS; break;
2562 default:
2563 fprintf(stderr, "Unknown debugging flag: %c\n", *f);
2564 exit(1);
2565 break;
2566 }
2567 f++;
2568 }
2569 } else if (!strcmp(argv[j],"--stats")) {
2570 Modes.stats = 1;
2571 } else if (!strcmp(argv[j],"--snip") && more) {
2572 snipMode(atoi(argv[++j]));
2573 exit(0);
2574 } else if (!strcmp(argv[j],"--help")) {
2575 showHelp();
2576 exit(0);
2577 } else {
2578 fprintf(stderr,
2579 "Unknown or not enough arguments for option '%s'.\n\n",
2580 argv[j]);
2581 showHelp();
2582 exit(1);
2583 }
2584 }
2585
2586 /* Setup for SIGWINCH for handling lines */
2587 if (Modes.interactive == 1) signal(SIGWINCH, sigWinchCallback);
2588
2589 /* Initialization */
2590 modesInit();
2591 if (Modes.net_only) {
2592 fprintf(stderr,"Net-only mode, no RTL device or file open.\n");
2593 } else if (Modes.filename == NULL) {
2594 modesInitRTLSDR();
2595 } else {
2596 if (Modes.filename[0] == '-' && Modes.filename[1] == '\0') {
2597 Modes.fd = STDIN_FILENO;
2598 } else if ((Modes.fd = open(Modes.filename,O_RDONLY)) == -1) {
2599 perror("Opening data file");
2600 exit(1);
2601 }
2602 }
2603 if (Modes.net) modesInitNet();
2604
2605 /* If the user specifies --net-only, just run in order to serve network
2606 * clients without reading data from the RTL device. */
2607 while (Modes.net_only) {
2608 backgroundTasks();
2609 modesWaitReadableClients(100);
2610 }
2611
2612 /* Create the thread that will read the data from the device. */
2613 pthread_create(&Modes.reader_thread, NULL, readerThreadEntryPoint, NULL);
2614
2615 pthread_mutex_lock(&Modes.data_mutex);
2616 while(1) {
2617 if (!Modes.data_ready) {
2618 pthread_cond_wait(&Modes.data_cond,&Modes.data_mutex);
2619 continue;
2620 }
2621 computeMagnitudeVector();
2622
2623 /* Signal to the other thread that we processed the available data
2624 * and we want more (useful for --ifile). */
2625 Modes.data_ready = 0;
2626 pthread_cond_signal(&Modes.data_cond);
2627
2628 /* Process data after releasing the lock, so that the capturing
2629 * thread can read data while we perform computationally expensive
2630 * stuff * at the same time. (This should only be useful with very
2631 * slow processors). */
2632 pthread_mutex_unlock(&Modes.data_mutex);
2633 detectModeS(Modes.magnitude, Modes.data_len/2);
2634 backgroundTasks();
2635 pthread_mutex_lock(&Modes.data_mutex);
2636 if (Modes.exit) break;
2637 }
2638
2639 /* If --ifile and --stats were given, print statistics. */
2640 if (Modes.stats && Modes.filename) {
2641 printf("%lld valid preambles\n", Modes.stat_valid_preamble);
2642 printf("%lld demodulated again after phase correction\n",
2643 Modes.stat_out_of_phase);
2644 printf("%lld demodulated with zero errors\n",
2645 Modes.stat_demodulated);
2646 printf("%lld with good crc\n", Modes.stat_goodcrc);
2647 printf("%lld with bad crc\n", Modes.stat_badcrc);
2648 printf("%lld errors corrected\n", Modes.stat_fixed);
2649 printf("%lld single bit errors\n", Modes.stat_single_bit_fix);
2650 printf("%lld two bits errors\n", Modes.stat_two_bits_fix);
2651 printf("%lld total usable messages\n",
2652 Modes.stat_goodcrc + Modes.stat_fixed);
2653 }
2654
2655 rtlsdr_close(Modes.dev);
2656 return 0;
2657 }
2658
2659
2660