Resurrection project • stable source release • 5 October 2026

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.

Why this exists

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.

Hardware support

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.

The included command-line tool

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;
New in 0.1.51 • travel feeder

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
Important: the durable collector queue is a feeder feature and remains opt-in in the library. Normal ADS-B Radar use does not gain a new per-contact SQLite write path merely by updating libadsb-reader.
Build & install

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.

C API

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 flagData
ADSB_FIELD_CALLSIGNADS-B callsign
ADSB_FIELD_ALTITUDEBarometric altitude in feet
ADSB_FIELD_SPEEDGround speed in knots
ADSB_FIELD_HEADINGTrack / heading in degrees
ADSB_FIELD_POSITIONGlobal airborne CPR latitude / longitude
ADSB_FIELD_SQUAWKMode A squawk, including 7500 / 7600 / 7700 when transmitted
ADSB_FIELD_REGISTRATIONOptional resolver registration
ADSB_FIELD_AIRCRAFT_TYPEOptional resolver aircraft type
ADSB_FIELD_FLIGHT_ROUTEOptional origin / destination codes
ADSB_FIELD_AIRCRAFT_OPERATOROptional aircraft operator information
ADSB_FIELD_FLIGHT_AIRLINEOptional flight airline information
ADSB_FIELD_ORIGIN_AIRPORTOptional origin airport name and coordinates
ADSB_FIELD_DESTINATION_AIRPORTOptional destination airport name and coordinates
Optional Museum resolver

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.

Privacy / network note. Resolver mode contributes one snapshot per aircraft contact to the ACARSd collector. A contact remains active until that ICAO24 has not been seen for 15 minutes. If you only want local decoding, simply do not enable --resolve.

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
A twenty-year detour back into RAM

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.

~101k/sSQLite • 1 million lookup benchmark
~770k/scollect.[ch] • 1 million lookup benchmark
~7×measured lookup speed-up in this workload

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.

Software archaeology with a benchmark: code written more than twenty years ago now has a production job again inside the modern reader.
0.1.51 engineering notes

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.
Scope & limitations

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).