libadsb-reader
One native Linux API for ADS-B receivers spanning more than two decades: RTL-SDR, the classic Kinetic SBS-1 and AirNav RadarBox V1 / RB-1, plus optional SDRplay API 3.x support. Receive, demodulate and decode Mode-S / ADS-B locally without a vendor application or network bridge.
Old receivers. New Linux code.
The ACARSd Museum began as an archive of software, screenshots, reports and stories. In 2026 it became an active laboratory again. While restoring the old receiving setup, we wanted to use the original ADS-B hardware directly under Linux instead of treating it as a display piece.
The result is libadsb-reader: a common receiver, demodulator and Mode-S/ADS-B decoder API. It began with clean-room/interoperability-oriented support for the Museum's SBS-1 and RadarBox hardware and now also supports modern RTL-SDR receivers and an optional SDRplay backend.
Kinetic SBS-1: the FT2232 USB protocol, startup exchange, packet framing, decryption and Mode-S extraction were reconstructed for native Linux use.
AirNav RadarBox V1 / RB-1: the FTDI/D2XX-style setup, challenge/response unlock and proprietary sample stream were reconstructed, including demodulation into 56- and 112-bit Mode-S frames.
One API: all receiver backends feed the same raw-frame and decoded-message callbacks.
RTL-SDR: modern 1090 MHz reception through librtlsdr, including RTL-SDR Blog V4 support, shared PPM demodulation, linear 2.4 → 8 MS/s IQ resampling and selectable tuner gain.
SDRplay: optional API 3.x backend using the same decoder path; no SDRplay SDK dependency is introduced into the default build.
2026 performance work: the live reader now coalesces redundant high-rate state updates before they reach applications, while event changes remain immediate. This keeps the bounded message queue healthy even under busy RTL-SDR reception.
Old code, new job: the historic collect.[ch] collection code was brought back for hot in-memory lookups of standing aircraft data. On the Museum benchmark it was roughly seven times faster than repeated SQLite lookups.
What the library talks to
Kinetic SBS-1
USB 0403:6010 · FT2232
- Native libusb access
- Reconstructed startup challenge/response
- SBS packet framing and decryption
- Packet CRC verification
- Mode-S extraction from packet types 0x01 and 0x07
Tested with the Museum's original SBS-1 hardware.
AirNav RadarBox V1 / RB-1
USB 0403:bb80 · FTDI
- Native libusb access
- FTDI/D2XX-style device setup
- Reconstructed RadarBox challenge/response unlock
- Proprietary 56/112-bit sample-stream demodulation
- Mode-S CRC / Address-Parity validation
Tested with RadarBox V1 / RB-1. Other RadarBox generations are not claimed as supported.
RTL-SDR / RTL-SDR Blog V4
optional librtlsdr build · RTLSDR=1
- 1090 MHz reception at 2.4 MS/s
- Phase-continuous linear IQ resampling to 8 MS/s
- Shared Mode-S preamble / PPM demodulator
- Automatic or manual tuner gain via --rtlsdr-gain
- Verbose DF and ADS-B Type Code receive diagnostics
RTL-SDR Blog V4 support is provided through the installed librtlsdr.
SDRplay RSP family
optional SDRplay API 3.x build · SDRPLAY=1
- 1090 MHz / 8 MS/s Zero-IF I/Q streaming
- 8 MHz bandwidth and 100 Hz AGC test configuration
- Shared Mode-S preamble / PPM demodulator
- Five-second verbose stream/demodulation diagnostics
- No SDRplay dependency in the default build
Initial hardware integration target: SDRplay RSP1B.
adsb-reader
The source tree includes adsb-reader, a small CLI built on the same public library API. It is useful for hardware tests, piping raw Mode-S into other software and as a working example of how to integrate the library.
# Discover supported receivers currently attached ./adsb-reader --list # Automatically choose a supported receiver ./adsb-reader --device auto # Explicit receiver selection ./adsb-reader --device radarbox ./adsb-reader --device sbs1 ./adsb-reader --device rtlsdr ./adsb-reader --device sdrplay # RTL-SDR gain: automatic or manual dB ./adsb-reader --device rtlsdr --rtlsdr-gain auto ./adsb-reader --device rtlsdr --rtlsdr-gain 43.9 # Conventional AVR raw output ./adsb-reader --device radarbox --avr
AVR mode emits conventional lines such as:
*8D4D22AC58AF16AB9FF9107EB3D3;
adsb-feeder — the receiver without the Radar box
Version 0.1.51 also includes adsb-feeder, a deliberately small standalone program built on libadsb-reader. It is intended for temporary receivers and travel installations where running the complete ADS-B Radar application would be unnecessary. Connect a supported receiver, give the feeder a location, and it can contribute aircraft contacts directly to the ACARSd/ADSB-Radar collector.
# Build the standalone feeder make feeder # First use at a new location ./adsb-feeder --forcenewid \ --location 43.7000,7.2500 \ --interactive # Later starts reuse the identity/location ./adsb-feeder
Designed for unreliable travel Internet
- Quiet by default; optional compact ncurses status cockpit with --interactive
- Persistent receiver identity and location
- --forcenewid creates a fresh receiver identity when moving to a new site
- Public six-character RADAR ID resolved and displayed separately from the internal receiver identity
- Last five newly seen aircraft shown in interactive mode
- Optional durable SQLite outbox: contacts are stored before upload and retried after connectivity returns
- Queue survives feeder shutdown and restart; confirmed uploads are removed only after HTTP success
Building on Debian / Ubuntu
sudo apt install build-essential pkg-config libusb-1.0-0-dev libsqlite3-dev libcurl4-openssl-dev libncurses-dev tar xzf libadsb-reader-0.1.51.tar.gz cd libadsb-reader-0.1.51 make # Build the standalone travel feeder make feeder # Optional RTL-SDR backend (install librtlsdr-dev first) make clean && make RTLSDR=1 # Optional SDRplay API 3.x backend make clean && make SDRPLAY=1 sudo make install sudo ldconfig
After installation, pkg-config can provide compiler and linker flags to applications:
pkg-config --cflags --libs libadsb-reader pkg-config --modversion libadsb-reader
The expected version for this release is 0.1.51.
Using libadsb-reader in your own program
The normal lifecycle is deliberately short: create a configuration, open a reader, register one or both callbacks, run the blocking receive loop, then close it. adsb_reader_stop() can be called from a signal handler or another control path to request shutdown.
#include <adsb-reader/adsb_reader.h>
char err[256];
adsb_reader_config_t cfg = {0};
cfg.device = ADSB_DEVICE_AUTO;
adsb_reader_t *r = adsb_reader_open(
&cfg, err, sizeof(err));
if (!r) {
/* handle err */
}
adsb_reader_set_raw_callback(r, raw_cb, NULL);
adsb_reader_set_message_callback(r, msg_cb, NULL);
adsb_reader_run(r);
adsb_reader_close(r);Two callback levels
Raw callback
adsb_raw_frame_t exposes the original 7- or 14-byte Mode-S frame, DF, ICAO address, timestamp and transport CRC state.
Decoded callback
adsb_message_t exposes decoded and accumulated fields through valid_fields and updated_fields.
This lets an application choose between handling Mode-S itself or using the common decoder.
The common decoder now handles DF11 all-call replies, DF17/DF18 Extended Squitter and classic Address/Parity formats DF0/DF4/DF5/DF16/DF20/DF21.
Decoded fields currently exposed
| Field flag | Data |
|---|---|
| ADSB_FIELD_CALLSIGN | ADS-B callsign |
| ADSB_FIELD_ALTITUDE | Barometric altitude in feet |
| ADSB_FIELD_SPEED | Ground speed in knots |
| ADSB_FIELD_HEADING | Track / heading in degrees |
| ADSB_FIELD_POSITION | Global airborne CPR latitude / longitude |
| ADSB_FIELD_SQUAWK | Mode A squawk, including 7500 / 7600 / 7700 when transmitted |
| ADSB_FIELD_REGISTRATION | Optional resolver registration |
| ADSB_FIELD_AIRCRAFT_TYPE | Optional resolver aircraft type |
| ADSB_FIELD_FLIGHT_ROUTE | Optional origin / destination codes |
| ADSB_FIELD_AIRCRAFT_OPERATOR | Optional aircraft operator information |
| ADSB_FIELD_FLIGHT_AIRLINE | Optional flight airline information |
| ADSB_FIELD_ORIGIN_AIRPORT | Optional origin airport name and coordinates |
| ADSB_FIELD_DESTINATION_AIRPORT | Optional destination airport name and coordinates |
Aircraft, flight and route enrichment
The core receiver and decoder do not require a network connection. Applications may optionally enable the ACARSd Museum resolver/collector with resolve_unknowns or the CLI option --resolve. Resolver data are cached locally in SQLite so USB reception is never blocked by HTTP.
./adsb-reader --device radarbox \ --resolve \ --location 46.8300,17.8300
The first resolver use requires a receiver location. It may be numeric coordinates or a text location such as Budapest. The location is persisted in the resolver database.
Default local resolver database:
root: /var/lib/libadsb-reader/resolver.db
normal user: $XDG_DATA_HOME/libadsb-reader/resolver.db
or ~/.local/share/libadsb-reader/resolver.db
Historic collect.[ch] vs. SQLite
One of the stranger 0.1.51 optimizations came from the old ACARSd/INLINE source archive. The reusable C collection implementation collect.[ch] was revived for standing aircraft data that are read constantly but change only when the data set is reloaded. Roughly 639,000 aircraft records are loaded into RAM once and then searched without a database round-trip on every lookup.
In the 10-million-lookup run, SQLite took roughly 98.5 seconds while the in-memory collection completed in about 13.9 seconds. Loading and sorting the approximately 639,000-record aircraft collection takes well under a second on the Raspberry Pi 5 used for ADS-B Radar, at the cost of roughly 145 MB of additional resident memory.
This is not a general claim that a C collection is “better than SQLite”. SQLite remains the right tool for persistent and relational data. The optimization targets a specific hot read path where an immutable in-memory index avoids repeated SQL work and reduces CPU/database pressure.
What changed in the stable release
- Output coalescer: every received ADS-B message still updates internal state, but redundant state callbacks are collapsed before reaching the application. Event changes remain immediate and motion updates are rate-limited per aircraft, dramatically reducing downstream callback pressure.
- Standing data in RAM: aircraft registration, type, manufacturer, serial number, year built, engines, operator, special livery and category can be served from the in-memory standing-data collection instead of repeated SQLite queries.
- Historic collections revived: collect.[ch] now provides the sorted in-memory lookup structure used by the reader for this hot path.
- Standalone adsb-feeder: make feeder builds a compact travel feeder with persistent identity/location, interactive status display and collector support.
- Durable offline queue: feeder mode can persist unsent contacts to SQLite and drain them after connectivity returns, including across program restarts. The feature is explicitly enabled by the feeder and remains off by default for ordinary library users.
- RTL-SDR gain control: --rtlsdr-gain auto|DB and adsb_reader_config_t.rtlsdr_gain_tenths_db let CLI users and applications select automatic or repeatable manual tuner gain.
- Improved RTL-SDR demodulation: the original zero-order-hold 2.4 → 8 MS/s converter was replaced by a phase-continuous linear IQ resampler to improve 0.5 µs Mode-S pulse-edge timing and weak-frame recovery without relaxing CRC/parity validation.
- Detailed RTL-SDR diagnostics: verbose mode reports preamble/candidate rates, accepted/raw/decoded/rejected frames, per-DF rates and ADS-B Type Code rates.
- Modern SDR backend: optional RTL-SDR support, including RTL-SDR Blog V4 through librtlsdr, joins the existing RadarBox, SBS-1 and optional SDRplay backends behind the same API.
- RadarBox unattended operation: threaded USB reception, a bounded producer/consumer queue, layered liveness diagnostics and staged recovery up to a cold USB reopen protect the proprietary RadarBox stream from downstream load and long-run stalls.
- Mode-S coverage: DF11, DF17/DF18 and Address/Parity DF0/DF4/DF5/DF16/DF20/DF21 remain supported, with guarded ICAO24 recovery for classic Address/Parity traffic.
- Beast output: the public adsb_raw_frame_to_beast() helper and CLI --beast mode provide standard Beast Binary framing for 56/112-bit Mode-S consumers.
- Resolver/collector: optional ACARSd enrichment remains asynchronous to USB reception through local caching and contact de-duplication.
A focused receiver library, not a universal ADS-B stack
What it is
A native Linux receiver library spanning classic USB receivers and modern SDR hardware, with shared Mode-S/ADS-B decoding, raw/Beast output and an example CLI.
What it is not
It is not claimed to support every SBS or RadarBox generation. SDRplay support requires API 3.x at build time, RTL-SDR requires librtlsdr, and the decoder intentionally remains smaller than full-featured mature ADS-B stacks. Raw Mode-S frames remain available for applications that need their own decoder.
The implementation is clean-room/interoperability-oriented code based on observed device communications and independently reconstructed behaviour. No vendor SDK is required. License: GNU Lesser General Public License v3.0 or later (LGPL-3.0-or-later).