gtec 0.0.2

Rust library and TUI for g.tec Unicorn Hybrid Black 8-channel EEG headset via the Unicorn C API (runtime-loaded)
Documentation

gtec

A Rust library and terminal UI for g.tec Unicorn EEG devices via the Unicorn C API and Bluetooth protocol.

Rust FFI wrapper with 100% API parity — all 16 functions from unicorn.h bound, all types mapped to #[repr(C)] Rust equivalents, plus a pure-Rust Bluetooth protocol implementation for macOS support.

Installation

cargo add gtec

Supported devices

Device Type Channels Resolution Hz Connection Status
Unicorn Hybrid Black EEG headset 8 EEG + 3 accel + 3 gyro + battery + counter (17 total) 24-bit 250 Classic Bluetooth RFCOMM ✅ Full support
Unicorn Naked OEM board (same HW) Same as Hybrid Black 24-bit 250 Classic Bluetooth RFCOMM ✅ Full support (same device)
Unicorn BCI Core-8 EEG amplifier kit 8 EEG 24-bit 250 Bluetooth 5 (BLE) ✅ Full support (libgtecble + pure-Rust BLE)

Unicorn BCI Core-8 support

The BCI Core-8 is supported via g.tec's official libgtecble BLE library, found in the gtec-ble PyPI package published by gtec-medical-engineering/gpype (g.tec's official Python SDK). The ffi_ble module binds all 9 exported functions:

Function Purpose
GTECBLE_GetApiVersion API version
GTECBLE_GetLastErrorText Last error description
GTECBLE_StartScanning Start BLE device scan
GTECBLE_StopScanning Stop BLE device scan
GTECBLE_RegisterDeviceDiscoveredCallback Callback when device found
GTECBLE_OpenDevice Connect to device by serial
GTECBLE_CloseDevice Disconnect device
GTECBLE_RegisterDataAvailableCallback Callback for streaming data
GTECBLE_GetDeviceInformation Device info (model, serial, firmware)

Platform support for BCI Core-8:

Platform Library Source
Windows (x64) libgtecble.dll (311 KB) PyPI gtec-ble wheel
macOS (universal) libgtecble.dylib (927 KB) PyPI gtec-ble wheel
Linux (x64) Pure-Rust ble.rs via btleplug No native lib needed

Other g.tec devices (not supported)

Device Why not supported
Unicorn tDCS Core-2 Transcranial stimulator, not EEG
g.USBamp Proprietary gAPI (commercial license, not on GitHub)
g.Nautilus Proprietary gAPI
g.HIamp Proprietary gAPI

Cross-platform

Works on Windows, Linux, and macOS.

Hybrid Black

Platform Backend Source
Windows (x64) Unicorn.dll via ffi unicorn-bi/Unicorn-Hybrid-Black-Windows-APIsc-api/Lib/
Linux (x64) libunicorn.so via ffi unicorn-bi/Unicorn-Suite-Hybrid-BlackUnicorn Linux C API/x64/Lib/
macOS Pure-Rust protocol.rs over BT RFCOMM No native lib needed

BCI Core-8

Platform Backend Source
Windows (x64) libgtecble.dll via ffi_ble PyPI gtec-ble v2.0.1
macOS (universal) libgtecble.dylib via ffi_ble PyPI gtec-ble v2.0.1
Linux (x64) Pure-Rust ble.rs via btleplug No native lib needed
All OS Pure-Rust ble.rs via btleplug cargo add gtec --features ble

The ble feature (enabled by default) provides a pure-Rust BLE backend using btleplug that works on all platforms without any native library. GATT UUIDs were extracted from g.tec's official libgtecble.dylib.

Note: g.tec does not provide a macOS native library, but this crate includes a pure-Rust Bluetooth protocol implementation (protocol.rs) that enables macOS support by communicating directly with the device over RFCOMM. The protocol was implemented from the official UnicornBluetoothProtocol.pdf.

Protocol details

The Unicorn uses classic Bluetooth RFCOMM with a simple binary protocol:

Element Format
Start acquisition 0x61 0x7C 0x87 → ACK 0x00 0x00 0x00
Stop acquisition 0x63 0x5C 0xC5 → ACK 0x00 0x00 0x00
Payload (250 Hz) 45 bytes per sample

Payload structure:

[0..1]   Header:        0xC0 0x00
[2]      Battery:       4-bit voltage in low nibble
[3..26]  EEG 1–8:       3 bytes each (24-bit signed, big-endian)
[27..32] Accelerometer:  2 bytes each (16-bit signed, little-endian) × 3 axes
[33..38] Gyroscope:      2 bytes each (16-bit signed, little-endian) × 3 axes
[39..42] Counter:        4 bytes (32-bit unsigned, little-endian)
[43..44] Footer:         0x0D 0x0A

Scale factors:

  • EEG: raw × 4500000 / 50331642 → µV
  • Accelerometer: raw / 4096 → g
  • Gyroscope: raw / 32.8 → °/s
  • Battery: (raw & 0x0F) / 15 × 100 → %

Quick start

use gtec::prelude::*;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let serials = UnicornDevice::scan(true)?;
    let mut device = UnicornDevice::open(&serials[0])?;

    println!("Info: {:?}", device.device_info()?);

    let scans = device.capture(UNICORN_SAMPLING_RATE * 4)?;
    for s in &scans[..5] {
        println!("EEG: {:?}", s.eeg());
    }

    device.close()?;
    Ok(())
}

Project layout

gtec-rs/
├── Cargo.toml
├── README.md
├── CHANGELOG.md
├── LICENSE
└── src/
    ├── lib.rs            # Crate root + prelude
    ├── main.rs           # CLI binary
    ├── bin/tui.rs        # ratatui TUI (8-channel EEG charts)
    ├── ffi.rs            # Runtime-loaded Unicorn C API for Hybrid Black (16 functions)
    ├── ffi_ble.rs        # Runtime-loaded libgtecble BLE API for BCI Core-8 (9 functions)
    ├── ble.rs            # Pure-Rust BLE backend for BCI Core-8 via btleplug (all OS)
    ├── types.rs          # #[repr(C)] types matching unicorn.h
    ├── protocol.rs       # Pure-Rust BT protocol (45-byte payload decode)
    ├── device.rs         # High-level device API
    ├── error.rs          # Error types
    ├── verify.rs         # SHA-256 integrity verification
    └── sandbox.rs        # OS-level network sandboxing
├── sdk/
│   ├── download.sh       # Download + verify native libraries
│   └── checksums.sha256  # Pinned SHA-256 hashes
├── examples/
│   ├── scan.rs           # Device discovery
│   ├── stream.rs         # Signal streaming
│   └── read_eeg.rs       # 4-second EEG capture
└── tests/
    └── types_tests.rs    # FFI type layout + constant + protocol tests

Dependencies

Crate Purpose
libloading Runtime DLL/so loading
btleplug Cross-platform BLE (optional, ble feature)
tokio Async runtime for BLE (optional, ble feature)
thiserror Error type derivation
log Logging facade
env_logger Log output
libc seccomp syscalls (Linux)
ratatui Terminal UI (optional)
crossterm Terminal backend (optional)

Running tests

cargo test

25 unit tests covering FFI type layouts, enum values, ABI struct sizes, protocol payload decoding (verified against official g.tec example), SHA-256 correctness, and constant validation — all without hardware.

License

MIT