HackRF One · Volume 5

HackRF One Volume 5 — Host Tooling (`hackrf_*` CLI, libhackrf, Python)

The day-to-day driver layer above libhackrf — capture, sweep, debug, automation

Contents

SectionTopic
1About this Volume
2Installing on Linux, macOS, Windows
· 2.1Linux (Debian/Ubuntu/Kali)
· 2.2macOS
· 2.3Windows
3Identification — hackrf_info
4Capture — hackrf_transfer
· 4.1Choosing sample rate, bandwidth, and gain
· 4.2Common capture recipes
5Transmit — hackrf_transfer -t
6Spectrum Survey — hackrf_sweep
7Clock — hackrf_clock
8Debug — hackrf_debug
9The libhackrf C API
10Python — pyhackrf2
11Common Workflows
· 11.1Capture-and-decode pipeline
· 11.2Continuous sweep dashboard
· 11.3Periodic capture cron job
12Cheatsheet Updates from this Volume
13Resources

1. About this Volume

Volume 4 covered firmware. This volume covers everything that runs on the host — the CLI tools shipped with hackrf-tools, the C library every other tool sits on (libhackrf), and the Python bindings that make automation tractable. With these you can capture IQ, sweep spectrum, push test signals out, debug clocking, identify hardware revisions, and integrate the HackRF into shell pipelines.

The order of the chapters follows the natural workflow: install → identify → capture → transmit → sweep → clock → automate.

2. Installing on Linux, macOS, Windows

2.1 Linux (Debian/Ubuntu/Kali)

sudo apt update
sudo apt install hackrf libhackrf-dev libhackrf0
sudo usermod -aG plugdev $USER     # if not already
# log out and back in, or newgrp plugdev

# Verify
hackrf_info

The Debian package ships udev rules at /lib/udev/rules.d/53-hackrf.rules that grant access to the plugdev group. If you built from source (Vol 4 §6), copy the rule file:

sudo cp host/libhackrf/53-hackrf.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules
sudo udevadm trigger

2.2 macOS

brew install hackrf
hackrf_info

Homebrew handles libhackrf as a dependency. macOS is the friendliest platform for casual HackRF work — drivers and permissions just work.

2.3 Windows

Two paths, both annoying:

WSL2 (recommended): Install Ubuntu under WSL2, install usbipd-win on the Windows host, attach the HackRF to WSL2’s usbipd. Then proceed as Linux. Adds 30 ms of latency vs native but otherwise indistinguishable.

Native Windows: Install Zadig^[https://zadig.akeo.ie/], replace the default Windows USB driver for the HackRF with WinUSB. Then download hackrf-tools Windows binaries from the GSG releases page. Tedious; updates require redoing Zadig.

Most serious HackRF users on Windows either dual-boot Linux for the actual radio work, or use WSL2 + usbipd-win. The whiteSHADOW1234 guide^[https://github.com/whiteSHADOW1234/HackRF-One-for-Windows] is the most readable Windows walk-through if you must go native.

3. Identification — hackrf_info

The first command run on a new bench setup:

$ hackrf_info
hackrf_info version: 2026.01.1
libhackrf version: 0.9 (2026.01.1)
Found HackRF
Index: 0
Serial number: 0000000000000000457863c834a45c0f
Board ID Number: 2 (HackRF One)
Firmware Version: 2026.01.1
Part ID Number: 0xa000cb3c 0x004f4747
Hardware Revision: r4

What each field tells you:

FieldMeaning
hackrf_info versionVersion of the CLI tool (matches host package)
libhackrf versionUnderlying library version
IndexMulti-device index (0, 1, 2, …)
Serial numberLPC4320 part-unique ID (32 hex digits, two 64-bit halves concatenated)
Board ID Number0=Jellybean, 1=Jawbreaker, 2=HackRF One, 3=rad1o, 4=HackRF Pro
Firmware VersionWhat’s running on LPC4320 right now
Part ID NumberLPC4320 silicon ID
Hardware Revisionr6+ self-reports; r1–r5 reads as “r1”; trust silkscreen for r1–r5

If you have multiple HackRFs plugged in, hackrf_info lists each. Many CLI tools accept -d <serial> to target a specific one.

4. Capture — hackrf_transfer

The day-to-day capture command:

hackrf_transfer -r capture.cfile \
    -f 433000000 \
    -s 2000000 \
    -g 32 -l 16 -a 1 \
    -n 4000000

Flags:

FlagMeaning
-r FILEReceive mode; write IQ samples to FILE
-t FILETransmit mode; read IQ samples from FILE
-f FREQCentre frequency, Hz (here 433 MHz)
-s RATESample rate, samples per second (here 2 MS/s; max 20 MS/s)
-b BWBaseband filter bandwidth (auto-selected from -s if omitted)
-g GAINVGA (post-baseband) gain, 0–62 dB in 2 dB steps
-l GAINLNA (pre-mixer) gain, 0–40 dB in 8 dB steps
-a 1/-a 0RX RF amp on/off (RF preamp; 14 dB nominal; can saturate)
-p 1/-p 0Bias-T enable on antenna port (3.3 V)
-n SAMPLESNumber of samples (omit for “until Ctrl-C”)
-x GAINTX VGA gain, 0–47 dB in 1 dB steps

The .cfile extension is convention — it means complex float32 (interleaved I, Q float32 pairs), the native GNU Radio format. hackrf_transfer writes interleaved 8-bit signed I, Q by default; many GNU Radio flowgraphs expect float32 — convert with:

# Convert int8 IQ → float32 IQ (Python one-liner)
python3 -c "
import numpy as np
raw = np.fromfile('capture.cfile', dtype=np.int8)
iq = raw.astype(np.float32) / 127.0
iq.tofile('capture.float32')
"

Or use GNU Radio’s Char to Float block (Vol 6 §4).

4.1 Choosing sample rate, bandwidth, and gain

Three coupled choices:

  • Sample rate sets the bandwidth captured. At -s 2000000 you see 2 MHz around -f. At -s 20000000 you see 20 MHz.
  • Baseband filter bandwidth (-b) is set by the MAX2837’s selectable IF filter (1.75/2.5/3.5/5/5.5/6/7/8/9/10/12/14/15/20/24/28 MHz). The firmware picks an appropriate value if -b is omitted; specify only if you want to deliberately roll off below the Nyquist of your sample rate (e.g. capture 2 MS/s with a 1.75 MHz IF filter to get aliasing-free margin).
  • Gain has three independent stages: RF amp (-a), LNA (-l, 0–40 in 8 dB steps), VGA (-g, 0–62 in 2 dB steps). Total gain range is ~115 dB. Aim for the noise floor at -50 dBFS in your spectrum view; raise gain until the noise lifts off the bottom, but stop before the strongest signal in band hits 0 dBFS (clipping).

Quick gain heuristic for unknown signals: start -a 0 -l 16 -g 16, capture briefly, look at signal levels, adjust.

4.2 Common capture recipes

FM broadcast survey:

hackrf_transfer -r fm.cfile -f 98000000 -s 2000000 -g 16 -l 16 -a 0 -n 4000000

ADS-B (1090 MHz, narrow bandwidth):

hackrf_transfer -r adsb.cfile -f 1090000000 -s 2000000 -g 32 -l 32 -a 1 -n 8000000

Sub-GHz remote-control (433 MHz ISM):

hackrf_transfer -r remote.cfile -f 433920000 -s 2000000 -g 24 -l 16 -a 0 -n 4000000

WiFi/BLE channel observation (2.4 GHz):

hackrf_transfer -r wifi.cfile -f 2412000000 -s 20000000 -g 24 -l 8 -a 0 -n 40000000

5. Transmit — hackrf_transfer -t

The same tool plays back IQ:

hackrf_transfer -t playback.cfile -f 433920000 -s 2000000 -x 30

-x is the TX VGA gain, 0–47 dB. Output power scales roughly linearly to ~+10 dBm at -x 47 with no signal compression. Real test signals (modulated, broadband) compress earlier.

Always confirm what you are transmitting and where. A captured commercial signal replayed over the air may violate FCC Part 15 (or your local equivalent) even if the source signal was on a license-free band. Vol 11 covers the legal envelope.

For bench testing into a dummy load (no radiation):

# Replace the antenna with a 50 Ω SMA dummy load
hackrf_transfer -t replay.cfile -f 433920000 -s 2000000 -x 30
# TX power dissipates in the dummy; nothing radiates.

6. Spectrum Survey — hackrf_sweep

hackrf_sweep steps the LO across a range and reports FFT power per bin. Output is CSV-friendly:

hackrf_sweep -f 80:1000 -w 100000 -n 8192 -a 0 -l 16 -g 20 -1 \
    > sweep.csv

Flags:

FlagMeaning
-f LO:HIFrequency range, MHz
-w BIN_HZBin width — total bins is roughly (HI-LO)*1e6 / BIN_HZ
-n FFTFFT size per step (8192 typical)
-a/-l/-gSame gain stages as hackrf_transfer
-1One-shot — sweep once and exit
-N COUNTRepeat the sweep COUNT times

The output CSV has columns: date, time, hz_low, hz_high, hz_bin_width, num_samples, [bin_db ...]. Plotting the result with gnuplot, Python+matplotlib, or pandas gives a usable spectrum picture. With -w 100000, a sweep from 80 to 1000 MHz produces 9200 bins per scan — comparable resolution to a $5000 lab spectrum analyser, with the dynamic-range caveat (8-bit ADC).

GitHub user pavsa/hackrf-spectrum-analyzer provides a real-time GUI on top of hackrf_sweep — useful for interactive band exploration.

7. Clock — hackrf_clock

Three operations:

hackrf_clock -i                 # show current input source (internal/external)
hackrf_clock --set-input-source external
hackrf_clock -o 1               # enable CLKOUT for cascading two devices

For dual-HackRF synchronised work:

  1. Wire the shared 10 MHz reference (typically a GPSDO) into both HackRFs’ CLKIN ports via a splitter.
  2. On both HackRFs: hackrf_clock --set-input-source external.
  3. Verify with hackrf_info — should now show external clock.
  4. Start both hackrf_transfer invocations as close to simultaneously as the host’s process scheduler allows.

The synchronisation checklist^[https://hackrf.readthedocs.io/en/latest/synchronization_checklist.html] is the GSG-authoritative reference for fine-tuning two-device coherence.

8. Debug — hackrf_debug

A direct-register-access tool for development. Reads/writes specific registers in the MAX2837 / RFFC5072 / Si5351C / CPLD configuration space.

hackrf_debug --max2837 -r 0x05    # read MAX2837 register 5
hackrf_debug --rffc5071 -r 0x0a   # read RFFC5072 register 10 (note: command says 5071, supports 5072)
hackrf_debug --si5351c -n 0       # multisynth setup register dump for output 0

Useful for:

  • Diagnosing why a particular gain setting doesn’t behave as expected.
  • Verifying CPLD bitstream is loaded.
  • Reverse-engineering register-level behaviour the firmware doesn’t expose.

9. The libhackrf C API

libhackrf.h exposes ~50 functions; the canonical list lives at host/libhackrf/src/hackrf.h in the repo. A minimal C capture:

#include <libhackrf/hackrf.h>
#include <stdio.h>

int rx_callback(hackrf_transfer *transfer) {
    fwrite(transfer->buffer, transfer->valid_length, 1, stdout);
    return 0;
}

int main() {
    hackrf_init();
    hackrf_device *device = NULL;
    hackrf_open(&device);
    hackrf_set_freq(device, 433920000);
    hackrf_set_sample_rate(device, 2000000);
    hackrf_set_lna_gain(device, 16);
    hackrf_set_vga_gain(device, 32);
    hackrf_start_rx(device, rx_callback, NULL);
    sleep(5);
    hackrf_stop_rx(device);
    hackrf_close(device);
    hackrf_exit();
    return 0;
}

Build: gcc capture.c -o capture -lhackrf.

The library is thread-safe per device handle. Calling sequence is fixed: init()open() → setters → start_rx() / start_tx()stop_*()close()exit().

10. Python — pyhackrf2

For automation, scripting, and notebook-style exploration:

pip install pyhackrf2

Equivalent script:

from pyhackrf2 import HackRF

hackrf = HackRF()
hackrf.sample_rate = 2_000_000
hackrf.center_freq = 433_920_000
hackrf.lna_gain = 16
hackrf.vga_gain = 32
samples = hackrf.read_samples(4_000_000)   # returns complex64 NumPy array
hackrf.close()

# samples is now ready for SciPy / NumPy DSP work
import numpy as np
power_db = 20 * np.log10(np.abs(np.fft.fftshift(np.fft.fft(samples[:8192]))))

pyhackrf2^[https://pypi.org/project/pyhackrf2/] is the active fork of pyhackrf and works against libhackrf 0.7+. It returns NumPy complex64 arrays directly, ready for scientific computing.

11. Common Workflows

11.1 Capture-and-decode pipeline

# 1. Spot the signal
hackrf_sweep -f 430:440 -w 50000 -1 > sweep.csv
# (visualise sweep.csv; identify a peak at 433.92 MHz)

# 2. Capture
hackrf_transfer -r capture.cfile -f 433920000 -s 2000000 -g 24 -l 16 -n 4000000

# 3. Inspect / decode
inspectrum capture.cfile      # waterfall + cursor analysis (Vol 7 §5)
# OR
urh capture.cfile             # protocol structure (Vol 7 §3)
# OR
gnuradio-companion my_decoder.grc    # custom flowgraph (Vol 6)

11.2 Continuous sweep dashboard

# In one terminal — feed sweep into a fifo
mkfifo /tmp/sweep
hackrf_sweep -f 100:6000 -w 1000000 -N 999999 > /tmp/sweep &

# In another terminal — read fifo, update a dashboard
python3 dashboard.py /tmp/sweep
# (your script reads CSV rows, plots in matplotlib FuncAnimation)

11.3 Periodic capture cron job

# Every hour, capture 30s of 433 MHz, archive
0 * * * * /usr/local/bin/hackrf_transfer \
    -r /var/log/rf/$(date +\%Y\%m\%d_\%H).cfile \
    -f 433920000 -s 2000000 -g 24 -l 16 -n 60000000

12. Cheatsheet Updates from this Volume

For Vol 12:

  • hackrf_info — first command on every fresh setup
  • hackrf_transfer -r FILE -f FREQ -s RATE -g VGA -l LNA -a AMP -n N
  • hackrf_transfer -t FILE -f FREQ -s RATE -x TX_VGA
  • hackrf_sweep -f LO:HI -w BIN -n FFT -1
  • hackrf_clock -i (status), --set-input-source external (use CLKIN)
  • hackrf_spiflash -R (reset to DFU), -w FILE (flash firmware)
  • hackrf_cpldjtag -x default.xsvf (CPLD reflash)
  • Gain stages: amp (0/14 dB), LNA (0–40 in 8 dB), VGA (0–62 in 2 dB)
  • Default file format: int8 IQ interleaved (NOT float32 — GNU Radio’s .cfile convention is float32)

13. Resources

ResourceURL
HackRF Tools (GSG docs)https://hackrf.readthedocs.io/en/latest/hackrf_tools.html
Sampling rate and baseband filtershttps://hackrf.readthedocs.io/en/latest/sampling_rate.html
Setting gain controls for RXhttps://hackrf.readthedocs.io/en/latest/setting_gain.html
libhackrf header (API reference)https://github.com/greatscottgadgets/hackrf/blob/main/host/libhackrf/src/hackrf.h
pyhackrf2 (Python bindings)https://pypi.org/project/pyhackrf2/
Synchronisation checklisthttps://hackrf.readthedocs.io/en/latest/synchronization_checklist.html
External clock interfacehttps://hackrf.readthedocs.io/en/latest/external_clock_interface.html
pavsa/hackrf-spectrum-analyzer GUIhttps://github.com/pavsa/hackrf-spectrum-analyzer
Zadig (Windows USB driver setup)https://zadig.akeo.ie/
usbipd-win (USB to WSL2)https://github.com/dorssel/usbipd-win