A Rust bridge that connects libsigrok-compatible
hardware to ngscopeclient via the
SigrokOscilloscope driver in scopehal, using the twinlan transport
(text SCPI command socket + binary waveform data socket).
This project specifically adds support for Sipeed SLogic and its derivatives
through the upstream sipeed-slogic-analyzer libsigrok driver.
Note: End-to-end support requires both halves of the pipeline:
- This Rust bridge server (the contents of this directory)
- The C++
SigrokOscilloscopedriver in scopehal — shipped as a patch againstscopehal-apps/lib/scopehalunderpatches/.See
patches/README.mdfor how to apply, refresh, and rebase the patch.
Sipeed SLogic Combo and derivatives — libsigrok is built with
--disable-all-drivers --enable-sipeed-slogic-analyzer, so only the Sipeed
family is compiled in. (To enable other drivers, edit the configure flags in
libsigrok-sys/build/deps.rs.)
sigrok-bridge-server/
├── libsigrok-sys/ # -sys crate: FFI + native bootstrap
│ ├── build.rs # target dispatcher (linux / windows / macos)
│ └── build/
│ ├── common.rs # cache, fetch, extract, tool check
│ ├── deps.rs # per-library build fns, shared by all platforms
│ ├── linux.rs # Linux platform entry
│ ├── windows.rs # Windows MSYS2 UCRT64 platform entry
│ └── macos.rs # macOS platform entry
├── sigrok-bridge-common/ # SCPI parser, twinlan transport, wire protocol
├── sigrok-bridge/ # Production bridge
├── fake/ # Fake bridge (no hardware)
├── patches/ # scopehal C++ patch for the client side
└── docs/
├── ARCHITECTURE.md
├── BUILD.md # Deep dive: link order, deps, post-install surgery
├── DEVELOPMENT.md
└── SCPI-PROTOCOL.md
libsigrok-sys is the single source of truth for native linkage
(links = "sigrok" in Cargo.toml). On any supported host, cargo build
downloads and compiles libffi, zlib, libusb, libzip, pcre2, libiconv (Windows
only), glib2, and libsigrok from source into $OUT_DIR/prefix/, then
statically links them. The resulting binary depends only on the host OS
baseline (glibc on Linux, UCRT + Win32 on Windows, libSystem + frameworks
on macOS).
cargo build --release -p sigrok-bridge on any of the supported hosts, or
cross-compile from Linux to Windows.
| Host / Target | How | Output |
|---|---|---|
| Linux host → Linux | cargo build --release -p sigrok-bridge |
target/release/sigrok-bridge — ~5 MB, glibc-only |
| Windows host → Windows (MSYS2) | inside UCRT64 shell: cargo build --release -p sigrok-bridge |
target/release/sigrok-bridge.exe — Win32 + UCRT only |
| macOS host → macOS | cargo build --release -p sigrok-bridge |
target/release/sigrok-bridge — libSystem + frameworks |
| Linux host → Windows (cross) | cargo build --release --target x86_64-pc-windows-gnullvm -p sigrok-bridge |
target/x86_64-pc-windows-gnullvm/release/sigrok-bridge.exe — ~7 MB, Win32 + UCRT only |
Native builds compile every C dep (libffi / zlib / libusb / libzip / pcre2 / glib2 / libsigrok) from source — fully self-contained binaries.
Cross-build uses MSYS2 ucrt64 prebuilt packages (downloaded via pacman) +
compiles only libsigrok from source. Faster than full source cross, produces
the same UCRT-based .exe.
First build takes ~5–10 min. Subsequent builds are seconds; compiled .a
files cache in $OUT_DIR, source tarballs + MSYS2 packages live at
~/.cache/libsigrok-sys/ (survives cargo clean).
# One-time prereqs (pick one)
sudo pacman -S base-devel cmake ninja meson curl tar xz bzip2 \
autoconf automake libtool pkgconf # Arch
sudo apt install build-essential cmake ninja-build meson curl tar \
xz-utils bzip2 autoconf automake libtool pkg-config # Debian/Ubuntu
sudo dnf groupinstall 'Development Tools'
sudo dnf install cmake ninja-build meson curl tar xz bzip2 \
autoconf automake libtool pkgconf-pkg-config # Fedora
cargo build --release -p sigrok-bridgeVerify static linking:
$ ldd target/release/sigrok-bridge
linux-vdso.so.1
libm.so.6, libgcc_s.so.1, libc.so.6, ld-linux-x86-64.so.2-
Install MSYS2 (official installer).
-
Open the UCRT64 shell (
mingw-w64-ucrt-x86_64environment). -
Install toolchain:
pacman -S --needed \ mingw-w64-ucrt-x86_64-gcc \ mingw-w64-ucrt-x86_64-rust \ mingw-w64-ucrt-x86_64-cmake \ mingw-w64-ucrt-x86_64-ninja \ mingw-w64-ucrt-x86_64-meson \ mingw-w64-ucrt-x86_64-pkgconf \ mingw-w64-ucrt-x86_64-python \ autoconf automake libtool make \ curl tar xz bzip2 sed git patch -
Build:
cd path/to/sigrok-bridge-server cargo build --release -p sigrok-bridge
Output: target\release\sigrok-bridge.exe. Verify no non-system DLL deps via
objdump -p sigrok-bridge.exe | grep 'DLL Name'.
Linux host compiling a Windows .exe via llvm-mingw + MSYS2 packages. Uses
x86_64-pc-windows-gnullvm (UCRT).
-
Install toolchain (Arch example):
rustup target add x86_64-pc-windows-gnullvm sudo pacman -S mingw-w64-binutils pacman fakeroot autoconf automake libtool \ pkgconf make curl tar sed bash yay -S llvm-mingw-w64-toolchain-ucrt-bin # AUR — provides /opt/llvm-mingw-ucrt/ # or download github.com/mstorsjo/llvm-mingw releases and add bin/ to PATHOn Debian/Ubuntu:
sudo apt install mingw-w64 pacman-package-manager fakeroot \ autoconf automake libtool pkg-config make curl tar sed bash # llvm-mingw: download a release from github.com/mstorsjo/llvm-mingw -
Build:
cargo build --release --target x86_64-pc-windows-gnullvm -p sigrok-bridge
How it works:
build/msys2.rsrunsfakeroot pacman -Sywto download MSYS2 ucrt64.pkg.tar.zstfiles (glib2, libusb, libzip + transitive deps) into~/.cache/libsigrok-sys/msys2/, then extracts them to a sysroot under$OUT_DIR/sysroot/.- libsigrok is fetched from sipeed/libsigrok @ pinned commit and cross- compiled against the sysroot with llvm-mingw's clang.
- libtool's partial-link step (
ld -rforlibdrivers.o) uses Arch's GNUld.bfdvia theLDenv var — llvm-mingw's ld.lld doesn't accept-rin PE/COFF mode. - A
static-shim/dir with justlibunwind.a(symlink) is prepended to rustc's link search so the final.exehas nolibunwind.dlldep.
Output: target/x86_64-pc-windows-gnullvm/release/sigrok-bridge.exe (~7 MB).
Only Win32 API + UCRT api-ms-win-crt-*.dll as runtime deps.
-
Xcode command-line tools:
xcode-select --install -
Install build deps via Homebrew:
brew install autoconf automake libtool pkg-config cmake ninja meson \ curl xz bzip2 -
Build:
cargo build --release -p sigrok-bridge
Output: target/release/sigrok-bridge (Mach-O). Verify with
otool -L target/release/sigrok-bridge — should show only libSystem.B.dylib
IOKit.framework+CoreFoundation.framework.
LIBSIGROK_COMMIT— pin libsigrok to a different upstream SHA (default: tracked inbuild/common.rs::LIBSIGROK_COMMIT_DEFAULT)LIBSIGROK_SYS_CACHE_DIR— tarball cache root (default:~/.cache/libsigrok-sys/)LIBSIGROK_SYS_GITHUB_MIRROR=https://ghproxy.com— route GitHub URLs through a mirror (for networks with restricted github.com access)
cargo run -p fake-bridge./target/release/sigrok-bridge # port 10101
./target/release/sigrok-bridge --pattern-mode Emulation # test pattern| Flag | Default | Description |
|---|---|---|
-d, --driver <NAME> |
sipeed-slogic-analyzer |
libsigrok driver name |
-p, --port <PORT> |
10101 |
TCP port for twinlan transport (data port = port + 1) |
--pattern-mode <MODE> |
(unset) | Built-in test patterns: Normal, "USB connection test", Emulation |
In the Add Instrument dialog:
- Driver:
sigrok - Transport:
twinlan - Path:
localhost:10101
The bridge accepts a single client at a time. On disconnect, the device is released and the next client can connect.
ngscopeclient (C++) sigrok-bridge (Rust) libsigrok (C)
───────────────── ────────────────────── ─────────────
SigrokOscilloscope ──SCPI──▶ scpi_handler ──▶ SigrokDevice ──▶ driver
◀─binary── data thread ◀── acquire() ◀── hardware
Full details in docs/ARCHITECTURE.md; wire protocol
in docs/SCPI-PROTOCOL.md.
- Device discovery via
sipeed-slogic-analyzerdriver - Sample rate enumeration (handles
a{sv}GVariant dict from the driver) - Sample depth fallback (1 KS to 1 TS, 1/2/5 step)
- Acquisition state machine (start / single / stop / force / armed)
- Continuous and one-shot capture
-
SR_CONF_PATTERN_MODEswitching (Normal / USB connection test / Emulation) - Digital channel data path (16-bit unit size)
- Graceful client disconnect (data thread shutdown flag)
- Cross-buffer edge trigger detection (software fallback keeps last state)