Elixir/BEAM bindings for Hamlib — the Ham Radio Control Library — via a Rustler NIF.

This wraps the Hamlib C API (the same surface the JS8Call Android port drives: rig_initrig_openrig_set_freq/rig_get_freq / rig_set_mode / rig_set_pttrig_closerig_cleanup) and exposes it to the BEAM. The point is not to reimplement CAT dialects in Elixir — Hamlib already encodes ~250 rigs' command sets, tested and field-proven — but to make that library callable from an OTP application.

Architecture

  Elixir  (Hamlib, Hamlib.Rig)                 lib/
       Rustler NIF
  Rust    (hamlib_nif crate)                   native/hamlib_nif/src/lib.rs
       bindgen over a thin C shim
  C shim  (hlx_* flat functions)               native/hamlib_nif/c_src/hamlib_shim.{c,h}
       links -lhamlib
  libhamlib  (the actual Hamlib C library)

Why a C shim instead of bindgen-on-rig.h?

Hamlib's public headers wrap the hot calls in __builtin_FUNCTION() macros, e.g. #define rig_set_freq(r,v,f) rig_set_freq(r,v,f,__builtin_FUNCTION()) — so the real ABI symbol takes an extra trailing const char * the macro injects for logging. bindgen run directly against rig.h binds the underlying symbol and loses the macro, which is a footgun. The shim (hamlib_shim.c) #includes rig.h so the macros apply correctly, owns the RIG * handle lifetime, and exposes flat hlx_* functions with plain signatures and translated error codes. bindgen binds the shim, not Hamlib's macro-mangled surface.

Serial I/O on Android (the open question)

On desktop, Hamlib opens a serial device path (/dev/ttyUSB0) and owns the fd. On Android there is no /dev/tty* access for USB serial — the CP2102 is reached through the Android USB host API (the same UsbDeviceConnection the modem app already owns). Bridging Hamlib's serial layer to that fd is the load-bearing problem for the on-device target and is tracked separately; host development and testing here use a real serial path or rigctld/dummy rig so the BEAM↔Hamlib seam can be built and validated before the Android serial bridge lands.

Status

Scaffolding. Host build against Homebrew Hamlib 4.6.5 first; Android NDK cross-compile and the USB-serial bridge follow.