gs_usb

Crates.iogs_usb
lib.rsgs_usb
version0.1.1
created_at2026-01-13 13:29:58.051149+00
updated_at2026-01-15 10:43:03.284129+00
descriptionGS-USB protocol implementation for CAN adapters
homepage
repositoryhttps://github.com/maksimdrachov/gs_usb_rs
max_upload_size
id2040166
size214,599
(maksimdrachov)

documentation

README

gs_usb - GS-USB Protocol Implementation for Rust

A Rust implementation of the GS-USB protocol for communicating with CAN bus adapters like candleLight, CANable, and other GS-USB compatible devices.

Features

  • Classic CAN Support: Up to 1 Mbps bitrate
  • CAN FD Support: Up to 10 Mbps data rate with flexible data length
  • Hardware Timestamps: Microsecond-precision timestamps from the device
  • Multiple Operating Modes: Normal, listen-only, loopback, and one-shot modes
  • Device State Monitoring: Error counters and bus state information
  • Cross-Platform: Works on Linux, macOS, and Windows

Supported Devices

  • GS-USB devices (VID: 0x1D50, PID: 0x606F)
  • candleLight (VID: 0x1209, PID: 0x2323)
  • CES CANext FD (VID: 0x1CD2, PID: 0x606F)
  • ABE CANdebugger FD (VID: 0x16D0, PID: 0x10B8)

Installation

Add this to your Cargo.toml:

[dependencies]
gs_usb = "0.1"

System Dependencies

This crate requires libusb to be installed:

Linux (Debian/Ubuntu):

sudo apt-get install libusb-1.0-0-dev

Linux (Fedora):

sudo dnf install libusb1-devel

macOS:

brew install libusb

Windows: Download and install libusb from https://libusb.info/

Quick Start

use gs_usb::{GsUsb, GsUsbFrame, GS_CAN_MODE_NORMAL, GS_CAN_MODE_HW_TIMESTAMP};
use std::time::Duration;

fn main() -> gs_usb::Result<()> {
    // Scan for devices
    let devices = GsUsb::scan()?;
    if devices.is_empty() {
        println!("No GS-USB device found");
        return Ok(());
    }

    let mut dev = devices.into_iter().next().unwrap();

    // Configure bitrate (250 kbps)
    dev.set_bitrate(250000)?;

    // Start the device
    dev.start(GS_CAN_MODE_NORMAL | GS_CAN_MODE_HW_TIMESTAMP)?;

    // Send a frame
    let data = [0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0];
    let frame = GsUsbFrame::with_data(0x7FF, &data);
    dev.send(&frame)?;

    // Read frames
    loop {
        match dev.read(Duration::from_millis(100)) {
            Ok(frame) => println!("RX  {}", frame),
            Err(gs_usb::GsUsbError::ReadTimeout) => continue,
            Err(e) => return Err(e),
        }
    }
}

Examples

Run the examples with:

# Basic usage example
cargo run --example gs_usb_example

# Device initialization sequence
cargo run --example device_initialization

# CAN FD channel start sequence
cargo run --example channel_start_sequence

# Test all supported bitrates
cargo run --example test_all_bitrates

# Test GET_STATE feature
cargo run --example test_get_state

Supported Bitrates

Classic CAN (87.5% sample point)

Bitrate 80 MHz 40 MHz
10 kbps
20 kbps
50 kbps
100 kbps
125 kbps
250 kbps
500 kbps
800 kbps
1 Mbps

CAN FD Data Phase (75% sample point)

Data Bitrate 80 MHz 40 MHz
2 Mbps
4 Mbps
5 Mbps
8 Mbps
10 Mbps -

API Overview

Device Discovery

// Scan for all GS-USB devices
let devices = GsUsb::scan()?;

// Find a specific device by bus and address
let device = GsUsb::find(1, 5)?;

Configuration

// Set bitrate (classic CAN)
dev.set_bitrate(500000)?;

// Set CAN FD data bitrate
dev.set_data_bitrate(5000000)?;

// Set raw timing parameters
dev.set_timing(prop_seg, phase_seg1, phase_seg2, sjw, brp)?;

Operating Modes

use gs_usb::*;

// Normal mode with hardware timestamps
dev.start(GS_CAN_MODE_NORMAL | GS_CAN_MODE_HW_TIMESTAMP)?;

// Listen-only mode (no ACKs)
dev.start(GS_CAN_MODE_LISTEN_ONLY)?;

// Loopback mode for testing
dev.start(GS_CAN_MODE_LOOP_BACK)?;

// CAN FD mode
dev.start(GS_CAN_MODE_NORMAL | GS_CAN_MODE_FD)?;

Frame Types

use gs_usb::{GsUsbFrame, CAN_EFF_FLAG, CAN_RTR_FLAG};

// Standard frame (11-bit ID)
let frame = GsUsbFrame::with_data(0x123, &[0x01, 0x02, 0x03]);

// Extended frame (29-bit ID)
let frame = GsUsbFrame::with_data(0x12345678 | CAN_EFF_FLAG, &data);

// Remote transmission request
let frame = GsUsbFrame::with_data(0x123 | CAN_RTR_FLAG, &[]);

// CAN FD frame with BRS (bit rate switch)
let frame = GsUsbFrame::with_fd_data(0x123, &data_64_bytes, true);

Device Information

// Get device info (channels, firmware version)
let info = dev.device_info()?;
println!("Channels: {}", info.channel_count());
println!("FW: {:.1}", info.firmware_version());

// Get device capabilities
let cap = dev.device_capability()?;
println!("Clock: {:.1} MHz", cap.clock_mhz());
println!("Features: 0x{:08x}", cap.feature);

// Check CAN FD support
if dev.supports_fd()? {
    println!("CAN FD is supported");
}

// Get bus state and error counters
if dev.supports_get_state()? {
    let state = dev.get_state(0)?;
    println!("State: {}", state.state_name());
    println!("RX errors: {}", state.rxerr);
    println!("TX errors: {}", state.txerr);
}

Linux Permissions

To access USB devices without root on Linux, create a udev rule:

sudo tee /etc/udev/rules.d/99-gs_usb.rules << EOF
# GS-USB devices
SUBSYSTEM=="usb", ATTR{idVendor}=="1d50", ATTR{idProduct}=="606f", MODE="0666"
# candleLight
SUBSYSTEM=="usb", ATTR{idVendor}=="1209", ATTR{idProduct}=="2323", MODE="0666"
# CES CANext FD
SUBSYSTEM=="usb", ATTR{idVendor}=="1cd2", ATTR{idProduct}=="606f", MODE="0666"
# ABE CANdebugger FD
SUBSYSTEM=="usb", ATTR{idVendor}=="16d0", ATTR{idProduct}=="10b8", MODE="0666"
EOF

sudo udevadm control --reload-rules
sudo udevadm trigger

License

MIT License

Acknowledgments

This is a Rust port of the Python gs_usb library.

Commit count: 10

cargo fmt