use gs_usb::{
DeviceCapability, DeviceInfo, GsUsb, GsUsbError, GS_CAN_FEATURE_BERR_REPORTING,
GS_CAN_FEATURE_BT_CONST_EXT, GS_CAN_FEATURE_FD, GS_CAN_FEATURE_GET_STATE,
GS_CAN_FEATURE_HW_TIMESTAMP, GS_CAN_FEATURE_IDENTIFY, GS_CAN_FEATURE_LISTEN_ONLY,
GS_CAN_FEATURE_LOOP_BACK, GS_CAN_FEATURE_ONE_SHOT, GS_CAN_FEATURE_PAD_PKTS_TO_MAX_PKT_SIZE,
GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX, GS_CAN_FEATURE_TERMINATION,
GS_CAN_FEATURE_TRIPLE_SAMPLE, GS_CAN_FEATURE_USER_ID,
};
fn main() {
env_logger::init();
if let Err(e) = run() {
eprintln!("Error: {}", e);
std::process::exit(1);
}
}
fn send_host_format(dev: &mut GsUsb) {
println!("=== Step 1: HOST_FORMAT ===");
match dev.send_host_format() {
Ok(()) => println!("HOST_FORMAT sent successfully (little-endian byte order)"),
Err(e) => println!("HOST_FORMAT failed (may be optional on this device): {}", e),
}
println!();
}
fn get_device_config(dev: &mut GsUsb) -> Result<DeviceInfo, GsUsbError> {
println!("=== Step 2: DEVICE_CONFIG ===");
let device_info = dev.device_info()?;
println!(
"Number of CAN channels: {} (icount={})",
device_info.channel_count(),
device_info.icount
);
println!(
"Firmware version: {:.1} (raw={})",
device_info.firmware_version(),
device_info.fw_version
);
println!(
"Hardware version: {:.1} (raw={})",
device_info.hardware_version(),
device_info.hw_version
);
println!();
Ok(device_info)
}
fn get_bt_const(dev: &mut GsUsb) -> Result<DeviceCapability, GsUsbError> {
println!("=== Step 3: BT_CONST (Bit Timing Constraints) ===");
let capability = dev.device_capability()?;
println!("Feature bitfield: 0x{:08x}", capability.feature);
println!(
"Clock frequency: {:.1} MHz ({} Hz)",
capability.clock_mhz(),
capability.fclk_can
);
println!(
"TSEG1 range: {} - {}",
capability.tseg1_min, capability.tseg1_max
);
println!(
"TSEG2 range: {} - {}",
capability.tseg2_min, capability.tseg2_max
);
println!("SJW max: {}", capability.sjw_max);
println!(
"BRP range: {} - {} (increment: {})",
capability.brp_min, capability.brp_max, capability.brp_inc
);
println!();
println!("Supported features:");
let feature_names: [(u32, &str); 14] = [
(GS_CAN_FEATURE_LISTEN_ONLY, "LISTEN_ONLY"),
(GS_CAN_FEATURE_LOOP_BACK, "LOOP_BACK"),
(GS_CAN_FEATURE_TRIPLE_SAMPLE, "TRIPLE_SAMPLE"),
(GS_CAN_FEATURE_ONE_SHOT, "ONE_SHOT"),
(GS_CAN_FEATURE_HW_TIMESTAMP, "HW_TIMESTAMP"),
(GS_CAN_FEATURE_IDENTIFY, "IDENTIFY"),
(GS_CAN_FEATURE_USER_ID, "USER_ID"),
(
GS_CAN_FEATURE_PAD_PKTS_TO_MAX_PKT_SIZE,
"PAD_PKTS_TO_MAX_PKT_SIZE",
),
(GS_CAN_FEATURE_FD, "FD (CAN FD)"),
(
GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX,
"REQ_USB_QUIRK_LPC546XX",
),
(GS_CAN_FEATURE_BT_CONST_EXT, "BT_CONST_EXT"),
(GS_CAN_FEATURE_TERMINATION, "TERMINATION"),
(GS_CAN_FEATURE_BERR_REPORTING, "BERR_REPORTING"),
(GS_CAN_FEATURE_GET_STATE, "GET_STATE"),
];
for (flag, name) in &feature_names {
if (capability.feature & flag) != 0 {
println!(" - {}", name);
}
}
println!();
Ok(capability)
}
fn get_bt_const_ext(
dev: &mut GsUsb,
capability: &DeviceCapability,
) -> Result<Option<DeviceCapability>, GsUsbError> {
println!("=== Step 4: BT_CONST_EXT (CAN FD Timing Constraints) ===");
if (capability.feature & GS_CAN_FEATURE_BT_CONST_EXT) == 0 {
println!("BT_CONST_EXT not supported by this device (no CAN FD)");
println!();
return Ok(None);
}
match dev.device_capability_extended()? {
Some(cap_ext) => {
println!("CAN FD Data Phase Timing Constraints:");
if let (Some(dtseg1_min), Some(dtseg1_max)) = (cap_ext.dtseg1_min, cap_ext.dtseg1_max) {
println!(" DTSEG1 range: {} - {}", dtseg1_min, dtseg1_max);
}
if let (Some(dtseg2_min), Some(dtseg2_max)) = (cap_ext.dtseg2_min, cap_ext.dtseg2_max) {
println!(" DTSEG2 range: {} - {}", dtseg2_min, dtseg2_max);
}
if let Some(dsjw_max) = cap_ext.dsjw_max {
println!(" DSJW max: {}", dsjw_max);
}
if let (Some(dbrp_min), Some(dbrp_max), Some(dbrp_inc)) =
(cap_ext.dbrp_min, cap_ext.dbrp_max, cap_ext.dbrp_inc)
{
println!(
" DBRP range: {} - {} (increment: {})",
dbrp_min, dbrp_max, dbrp_inc
);
}
println!();
Ok(Some(cap_ext))
}
None => {
println!("BT_CONST_EXT request failed");
println!();
Ok(None)
}
}
}
fn run() -> gs_usb::Result<()> {
println!("Scanning for gs_usb devices...");
let devices = GsUsb::scan()?;
if devices.is_empty() {
println!("Can not find gs_usb device");
return Ok(());
}
let mut dev = devices.into_iter().next().unwrap();
println!("Found device: {}", dev);
println!();
send_host_format(&mut dev);
let device_info = get_device_config(&mut dev)?;
let capability = get_bt_const(&mut dev)?;
let bt_const_ext = get_bt_const_ext(&mut dev, &capability)?;
println!("{}", "=".repeat(50));
println!("Device initialization cycle complete!");
println!("Device has {} CAN channel(s)", device_info.channel_count());
if bt_const_ext.is_some() {
println!("CAN FD is supported (BT_CONST_EXT available)");
} else {
println!("Classic CAN only (no CAN FD)");
}
Ok(())
}