mirror of
https://github.com/intrepidcs/libicsneo.git
synced 2026-08-05 09:28:40 +02:00
API: Added icsneoc2.
Signed-off-by: David Rebbe <drebbe@intrepidcs.com>
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
debug/
|
||||
target/
|
||||
|
||||
# These are backup files generated by rustfmt
|
||||
**/*.rs.bk
|
||||
|
||||
# MSVC Windows builds of rustc generate these, which store debugging information
|
||||
*.pdb
|
||||
|
||||
# RustRover
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
Generated
+293
@@ -0,0 +1,293 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.71.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"itertools",
|
||||
"log",
|
||||
"prettyplease",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
|
||||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"libc",
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
|
||||
|
||||
[[package]]
|
||||
name = "icsneoc2rs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.169"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prettyplease"
|
||||
version = "0.2.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.96"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
@@ -0,0 +1,22 @@
|
||||
[package]
|
||||
name = "icsneoc2rs"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
name = "icsneoc2rs"
|
||||
crate-type = ["rlib", "staticlib", "cdylib"]
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[example]]
|
||||
name = "simple"
|
||||
path = "examples/simple.rs"
|
||||
|
||||
[dev-dependencies]
|
||||
scopeguard = "1.2.0"
|
||||
|
||||
[features]
|
||||
static = []
|
||||
|
||||
[build-dependencies]
|
||||
bindgen = "0.71.1"
|
||||
@@ -0,0 +1,40 @@
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn main() {
|
||||
// Tell cargo to look for shared libraries in the specified directory
|
||||
println!("cargo:rustc-link-search=../../../build");
|
||||
|
||||
// Tell cargo to tell rustc to link the system
|
||||
// shared library.
|
||||
println!("cargo:rustc-link-lib=icsneoc2");
|
||||
|
||||
// The bindgen::Builder is the main entry point
|
||||
// to bindgen, and lets you build up options for
|
||||
// the resulting bindings.
|
||||
let bindings = bindgen::Builder::default()
|
||||
// The input header we would like to generate
|
||||
// bindings for.
|
||||
.header("../../../include/icsneo/icsneoc2.h")
|
||||
.clang_arg("-I../../../include")
|
||||
// Tell cargo to invalidate the built crate whenever any of the
|
||||
// included header files changed.
|
||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
|
||||
.derive_default(true)
|
||||
.derive_debug(true)
|
||||
.derive_partialeq(true)
|
||||
.derive_copy(true)
|
||||
.default_enum_style(bindgen::EnumVariation::Rust { non_exhaustive: true })
|
||||
.default_alias_style(bindgen::AliasVariation::TypeAlias)
|
||||
.generate_cstr(true)
|
||||
// Finish the builder and generate the bindings.
|
||||
.generate()
|
||||
// Unwrap the Result and panic on failure.
|
||||
.expect("Unable to generate bindings");
|
||||
|
||||
// Write the bindings to the $OUT_DIR/bindings.rs file.
|
||||
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||
bindings
|
||||
.write_to_file(out_path.join("bindings.rs"))
|
||||
.expect("Couldn't write bindings!");
|
||||
}
|
||||
@@ -0,0 +1,333 @@
|
||||
use icsneoc2rs::ffi::_icsneoc2_msg_bus_type_t::*;
|
||||
use icsneoc2rs::ffi::_icsneoc2_msg_type_t::*;
|
||||
use icsneoc2rs::ffi::_icsneoc2_netid_t;
|
||||
use icsneoc2rs::ffi::_icsneoc2_netid_t::*;
|
||||
use icsneoc2rs::ffi::_icsneoc2_open_options_t::*;
|
||||
use icsneoc2rs::ffi::icsneoc2_message_t;
|
||||
use icsneoc2rs::ffi::icsneoc2_msg_bus_type_t;
|
||||
use icsneoc2rs::ffi::icsneoc2_msg_type_t;
|
||||
use icsneoc2rs::ffi::icsneoc2_netid_t;
|
||||
use icsneoc2rs::Device;
|
||||
use icsneoc2rs::Error;
|
||||
use icsneoc2rs::Result as ICSNeoResult;
|
||||
|
||||
use scopeguard::defer;
|
||||
|
||||
fn main() -> ICSNeoResult<()> {
|
||||
print!("Finding devices... ");
|
||||
let devices = Device::find_all(255)?;
|
||||
println!(
|
||||
"OK, {} device{} found...",
|
||||
devices.len(),
|
||||
if devices.len() > 1 { "s" } else { "" }
|
||||
);
|
||||
for device in devices {
|
||||
device.device_is_valid()?;
|
||||
// Get description of the device
|
||||
let description = match device.device_description_get() {
|
||||
Ok(description) => description,
|
||||
Err(err) => {
|
||||
println!("Failed to get description of device: {err}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("{} @ Handle {:?}", description, device.handle);
|
||||
// Get/Set open options
|
||||
let mut open_options = match device.device_open_options_get() {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
println!("Failed to get open options of device: {err}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
// Disable Syncing RTC and going online
|
||||
open_options &= !(icsneoc2_open_options_sync_rtc as u32);
|
||||
open_options &= !(icsneoc2_open_options_go_online as u32);
|
||||
match device.device_open_options_set(open_options) {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("\tDevice open options: {open_options:#02x}");
|
||||
// Open the device
|
||||
print!("\tOpening device... ");
|
||||
match device.device_open() {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("OK");
|
||||
defer! {
|
||||
print_device_events(&device, &description).expect("Critical: Failed to print device events");
|
||||
}
|
||||
// Get timestamp resolution of the device
|
||||
print!("\tGetting timestamp resolution... ");
|
||||
let timestamp_resolution = match device.device_timestamp_resolution_get() {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("{timestamp_resolution}ns");
|
||||
// Get baudrates for HSCAN
|
||||
print!("\tGetting HSCAN baudrate... ");
|
||||
let baudrate = match device.device_baudrate_get(icsneoc2_netid_hscan) {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("{baudrate}mbit/s");
|
||||
// Get FD baudrates for HSCAN
|
||||
print!("\tGetting FD HSCAN baudrate... ");
|
||||
let fd_baudrate = match device.device_canfd_baudrate_get(icsneoc2_netid_hscan) {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("{fd_baudrate}mbit/s");
|
||||
// Set baudrates for HSCAN
|
||||
// saveToDevice: If this is set to true, the baudrate will be saved on the device
|
||||
// and will persist through a power cycle
|
||||
print!("\tSetting HSCAN baudrate... ");
|
||||
let save_to_device = false;
|
||||
match device.device_baudrate_set(icsneoc2_netid_hscan, baudrate, save_to_device) {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("OK");
|
||||
// Set FD baudrates for HSCAN
|
||||
print!("\tSetting FD HSCAN baudrate... ");
|
||||
match device.device_canfd_baudrate_set(icsneoc2_netid_hscan, fd_baudrate, save_to_device) {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("OK");
|
||||
// Get RTC
|
||||
print!("\tGetting RTC... ");
|
||||
let current_rtc = match device.device_rtc_get() {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("{current_rtc}");
|
||||
// Set RTC
|
||||
print!("\tSetting RTC... ");
|
||||
match device.device_rtc_set(current_rtc) {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("OK");
|
||||
// Get RTC
|
||||
print!("\tGetting RTC... ");
|
||||
let rtc = match device.device_rtc_get() {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("{rtc}");
|
||||
// Go online, start acking traffic
|
||||
print!("\tGoing online... ");
|
||||
match device.device_go_online(true) {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
// Redundant check to show how to check if the device is online, if the previous
|
||||
// icsneoc2_device_go_online call was successful we can assume we are online already
|
||||
let is_online = match device.device_is_online() {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("{}", if is_online { "Online" } else { "Offline" });
|
||||
// Transmit CAN messages
|
||||
if transmit_can_messages(&device).is_err() {
|
||||
continue;
|
||||
}
|
||||
println!("\tWaiting 1 second for messages...");
|
||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||
// Get the messages
|
||||
let messages = match device.device_messages_get(20000, 3000) {
|
||||
Ok(messages) => messages,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
// Process the messages
|
||||
if process_messages(&device, messages).is_err() {
|
||||
continue;
|
||||
}
|
||||
// Close the device
|
||||
print!("\tClosing device... ");
|
||||
match device.device_close() {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
print_error(&device, &description, err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("OK");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_error(device: &Device, device_description: &String, err: Error) {
|
||||
println!("Failed: {err}");
|
||||
print_device_events(device, device_description)
|
||||
.expect("Critical: Failed to print device events");
|
||||
}
|
||||
|
||||
fn transmit_can_messages(device: &Device) -> ICSNeoResult<()> {
|
||||
const MESSAGE_COUNT: usize = 100;
|
||||
println!("\tTransmitting {MESSAGE_COUNT} messages...");
|
||||
for i in 0..MESSAGE_COUNT {
|
||||
let message = match device.message_can_create(1) {
|
||||
Ok(messages) => messages[0],
|
||||
Err(err) => {
|
||||
println!("Failed to create CAN message #{i}: {err}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
device.message_netid_set(message, icsneoc2_netid_hscan)?;
|
||||
device.message_can_arbid_set(message, 0x10)?;
|
||||
device.message_can_canfd_set(message, true)?;
|
||||
device.message_can_extended_set(message, true)?;
|
||||
device.message_can_baudrate_switch_set(message, true)?;
|
||||
device.message_data_set(
|
||||
message,
|
||||
vec![
|
||||
(i >> 56 & 0xFF) as u8,
|
||||
(i >> 48 & 0xFF) as u8,
|
||||
(i >> 40 & 0xFF) as u8,
|
||||
(i >> 32 & 0xFF) as u8,
|
||||
(i >> 24 & 0xFF) as u8,
|
||||
(i >> 16 & 0xFF) as u8,
|
||||
(i >> 8 & 0xFF) as u8,
|
||||
(i & 0xFF) as u8,
|
||||
],
|
||||
)?;
|
||||
device.message_can_dlc_set(message, -1)?;
|
||||
device.device_messages_transmit(vec![message])?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn process_messages(device: &Device, messages: Vec<*mut icsneoc2_message_t>) -> ICSNeoResult<()> {
|
||||
let mut tx_count: u32 = 0;
|
||||
for (i, message) in messages.iter().enumerate() {
|
||||
// Get the message type
|
||||
let msg_type = device.message_type_get(*message)?;
|
||||
// Get the message type name
|
||||
let msg_type_name = device.message_type_name_get(msg_type)?;
|
||||
// Check if the message is a bus message, ignore otherwise
|
||||
if msg_type != icsneoc2_msg_type_bus as icsneoc2_msg_type_t {
|
||||
println!("\tIgnoring message type : {msg_type} ({msg_type_name})");
|
||||
continue;
|
||||
}
|
||||
// Get the message bus type
|
||||
let msg_bus_type = device.message_bus_type_get(*message)?;
|
||||
// Get the message type name
|
||||
let msg_bus_type_name = device.bus_type_name_get(msg_bus_type)?;
|
||||
// Check if message is a transmit message
|
||||
if device.message_is_transmit(*message)? {
|
||||
tx_count += 1;
|
||||
continue;
|
||||
}
|
||||
println!("\t{i} Message type: {msg_type} bus type: {msg_bus_type_name} ({msg_bus_type})\n");
|
||||
// Check if the message is a CAN message, ignore otherwise
|
||||
if msg_bus_type == icsneoc2_msg_bus_type_can as icsneoc2_msg_bus_type_t {
|
||||
let netid = device.message_netid_get(*message)?;
|
||||
let netid_name = device.netid_name_get(netid)?;
|
||||
let arbid = device.message_can_arbid_get(*message)?;
|
||||
let dlc = device.message_can_dlc_get(*message)?;
|
||||
let is_remote = device.message_can_is_remote(*message)?;
|
||||
let is_canfd = device.message_can_is_canfd(*message)?;
|
||||
let is_extended = device.message_can_is_extended(*message)?;
|
||||
let data = device.message_data_get(*message, 64)?;
|
||||
// Finally lets print the RX message
|
||||
println!("\t NetID: {netid_name} ({:#02x})\tArbID: {arbid:#02x}\t DLC: {dlc}\t Remote: {is_remote}\t \
|
||||
CANFD: {is_canfd}\t Extended: {is_extended}\t Data length: {}\n", netid as icsneoc2_netid_t,data.len());
|
||||
println!("\t Data: {data:#02x?}\n");
|
||||
} else {
|
||||
println!("\tIgnoring bus message type: {msg_bus_type} ({msg_bus_type_name})\n");
|
||||
}
|
||||
}
|
||||
println!(
|
||||
"\tReceived {} messages total, {} were TX messages",
|
||||
messages.len(),
|
||||
tx_count
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_device_events(device: &Device, device_description: &String) -> ICSNeoResult<()> {
|
||||
let events = match device.device_events_get(1024) {
|
||||
Ok(events) => events,
|
||||
Err(err) => {
|
||||
println!("Failed to get device events: {err}");
|
||||
return Err(err);
|
||||
}
|
||||
};
|
||||
for (i, event) in events.iter().enumerate() {
|
||||
let description = match device.event_description_get(*event) {
|
||||
Ok(description) => description,
|
||||
Err(err) => {
|
||||
println!("Failed to get event description: {err}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("\t{device_description}: Event {i}: {description}");
|
||||
}
|
||||
// Get global events
|
||||
let global_events = match device.events_get(1024) {
|
||||
Ok(events) => events,
|
||||
Err(err) => {
|
||||
println!("Failed to get global events: {err}");
|
||||
return Err(err);
|
||||
}
|
||||
};
|
||||
for (i, event) in global_events.iter().enumerate() {
|
||||
let description = match device.event_description_get(*event) {
|
||||
Ok(description) => description,
|
||||
Err(err) => {
|
||||
println!("Failed to get event description: {err}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
println!("\t{device_description}: Global Event {i}: {description}");
|
||||
}
|
||||
println!(
|
||||
"\t{device_description}: Received {} events and {} global events\n",
|
||||
events.len(),
|
||||
global_events.len()
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
#![allow(non_upper_case_globals)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
||||
@@ -0,0 +1,902 @@
|
||||
pub mod ffi;
|
||||
|
||||
use ffi::_icsneoc2_error_t::{icsneoc2_error_invalid_device, icsneoc2_error_success};
|
||||
use ffi::_icsneoc2_open_options_t::*;
|
||||
use ffi::*;
|
||||
|
||||
use std::ffi::CString;
|
||||
use std::fmt::Display;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Error {
|
||||
/// icsneoc2 API error
|
||||
APIError(icsneoc2_error_t, String),
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Error::APIError(error_code, error_string) => write!(f, "API Error: \"{}\" ({})", error_string, error_code),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type Result<T> = core::result::Result<T, Error>;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Device {
|
||||
/// Handle to the device.
|
||||
pub handle: *mut icsneoc2_device_t,
|
||||
}
|
||||
|
||||
impl Drop for Device {
|
||||
fn drop(&mut self) {
|
||||
// Make sure the device is closed before we go out of scope.
|
||||
self.device_close().expect("Failed to close device!");
|
||||
}
|
||||
}
|
||||
|
||||
impl Device {
|
||||
pub fn find_all(device_count: u32) -> Result<Vec<Self>> {
|
||||
// Find all the devices
|
||||
const MAX_DEVICE_COUNT: u32 = 255;
|
||||
let mut devices: [*mut icsneoc2_device_t; MAX_DEVICE_COUNT as usize] =
|
||||
[std::ptr::null_mut(); 255];
|
||||
let mut devices_count: u32 = if device_count > MAX_DEVICE_COUNT {
|
||||
MAX_DEVICE_COUNT
|
||||
} else {
|
||||
device_count
|
||||
};
|
||||
let res = unsafe {
|
||||
icsneoc2_device_find_all(
|
||||
devices.as_mut_ptr(),
|
||||
&mut devices_count as *mut u32,
|
||||
std::ptr::null_mut(),
|
||||
)
|
||||
};
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
// Return the results
|
||||
let found_devices: Vec<Self> = devices[..devices_count as usize]
|
||||
.iter()
|
||||
.map(|d| Self { handle: *d })
|
||||
.collect();
|
||||
Ok(found_devices)
|
||||
}
|
||||
|
||||
pub fn bus_type_name_get(&self, bus_type: icsneoc2_msg_bus_type_t) -> Result<String> {
|
||||
// Get the string
|
||||
let mut str: Vec<u8> = vec![0; 255];
|
||||
let mut str_length: u32 = 255;
|
||||
let res = unsafe {
|
||||
icsneoc2_bus_type_name_get(bus_type, str.as_mut_ptr() as *mut i8, &mut str_length)
|
||||
};
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
// Convert the vec to an String
|
||||
str.resize(str_length as usize, 0);
|
||||
let str_string = {
|
||||
CString::new(str)
|
||||
.expect("CString::new failed")
|
||||
.into_string()
|
||||
.expect("CString::new::into_string")
|
||||
};
|
||||
Ok(str_string)
|
||||
}
|
||||
|
||||
pub fn device_baudrate_get(&self, netid: _icsneoc2_netid_t) -> Result<u64> {
|
||||
let mut value: u64 = 0;
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_device_baudrate_get(self.handle, netid as icsneoc2_netid_t, &mut value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn device_baudrate_set(
|
||||
&self,
|
||||
netid: _icsneoc2_netid_t,
|
||||
value: u64,
|
||||
save: bool,
|
||||
) -> Result<()> {
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_device_baudrate_set(self.handle, netid as icsneoc2_netid_t, value, save) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn device_canfd_baudrate_get(&self, netid: _icsneoc2_netid_t) -> Result<u64> {
|
||||
let mut value: u64 = 0;
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_device_canfd_baudrate_get(self.handle, netid as icsneoc2_netid_t, &mut value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn device_canfd_baudrate_set(
|
||||
&self,
|
||||
netid: _icsneoc2_netid_t,
|
||||
value: u64,
|
||||
save: bool,
|
||||
) -> Result<()> {
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_device_canfd_baudrate_set(self.handle, netid as icsneoc2_netid_t, value, save) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn device_close(&self) -> Result<()> {
|
||||
let res: icsneoc2_error_t = unsafe { ffi::icsneoc2_device_close(self.handle) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn device_description_get(&self) -> Result<String> {
|
||||
// Get the error code
|
||||
let mut description: Vec<u8> = vec![0; 255];
|
||||
let mut description_length: u32 = 255;
|
||||
let res = unsafe {
|
||||
icsneoc2_device_description_get(
|
||||
self.handle,
|
||||
description.as_mut_ptr() as *mut i8,
|
||||
&mut description_length,
|
||||
)
|
||||
};
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
// Convert the vec to an String
|
||||
description.resize(description_length as usize, 0);
|
||||
let description_str = {
|
||||
CString::new(description)
|
||||
.expect("CString::new failed")
|
||||
.into_string()
|
||||
.expect("CString::new::into_string")
|
||||
};
|
||||
Ok(description_str)
|
||||
}
|
||||
|
||||
pub fn device_events_get(&self, event_count: u32) -> Result<Vec<*mut icsneoc2_event_t>> {
|
||||
let mut events: Vec<*mut icsneoc2_event_t> =
|
||||
vec![std::ptr::null_mut(); event_count as usize];
|
||||
let mut event_count: u32 = event_count;
|
||||
let res: icsneoc2_error_t = unsafe {
|
||||
ffi::icsneoc2_device_events_get(self.handle, events.as_mut_ptr(), &mut event_count)
|
||||
};
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
events.resize(event_count as usize, std::ptr::null_mut());
|
||||
Ok(events)
|
||||
}
|
||||
|
||||
pub fn device_go_online(&self, go_online: bool) -> Result<()> {
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_device_go_online(self.handle, go_online) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn device_is_online(&self) -> Result<bool> {
|
||||
let mut is_online: bool = false;
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_device_is_online(self.handle, &mut is_online) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(is_online)
|
||||
}
|
||||
|
||||
pub fn device_is_online_supported(&self) -> Result<bool> {
|
||||
let mut is_online_supported: bool = false;
|
||||
let res: icsneoc2_error_t = unsafe {
|
||||
ffi::icsneoc2_device_is_online_supported(self.handle, &mut is_online_supported)
|
||||
};
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(is_online_supported)
|
||||
}
|
||||
|
||||
pub fn device_is_valid(&self) -> Result<bool> {
|
||||
let res: icsneoc2_error_t = unsafe { icsneoc2_device_is_valid(self.handle) };
|
||||
match res {
|
||||
res if res == icsneoc2_error_success as icsneoc2_error_t => Ok(true),
|
||||
res if res == icsneoc2_error_invalid_device as icsneoc2_error_t => Ok(false),
|
||||
_ => Err(Self::error_code_get(res)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn device_is_open(&self) -> Result<bool> {
|
||||
let mut is_open: bool = false;
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_device_is_open(self.handle, &mut is_open) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(is_open)
|
||||
}
|
||||
|
||||
pub fn device_is_disconnected(&self) -> Result<bool> {
|
||||
let mut is_disconnected: bool = false;
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_device_is_disconnected(self.handle, &mut is_disconnected) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(is_disconnected)
|
||||
}
|
||||
|
||||
pub fn device_load_default_settings(&self, save: bool) -> Result<()> {
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_device_load_default_settings(self.handle, save) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn device_message_count_get(&self) -> Result<u32> {
|
||||
let mut value: u32 = 0;
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_device_message_count_get(self.handle, &mut value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn device_message_polling_get(&self) -> Result<bool> {
|
||||
let mut value: bool = false;
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_device_message_polling_get(self.handle, &mut value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn device_message_polling_limit_get(&self) -> Result<u32> {
|
||||
let mut value: u32 = 0;
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_device_message_polling_limit_get(self.handle, &mut value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn device_message_polling_set(&self, enable: bool) -> Result<()> {
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_device_message_polling_set(self.handle, enable) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn device_message_polling_set_limit(&self, value: u32) -> Result<()> {
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_device_message_polling_set_limit(self.handle, value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn device_messages_get(
|
||||
&self,
|
||||
message_count: u32,
|
||||
timeout_ms: u32,
|
||||
) -> Result<Vec<*mut icsneoc2_message_t>> {
|
||||
let mut messages: Vec<*mut icsneoc2_message_t> =
|
||||
vec![std::ptr::null_mut(); message_count as usize];
|
||||
let mut message_count: u32 = message_count;
|
||||
let res: icsneoc2_error_t = unsafe {
|
||||
ffi::icsneoc2_device_messages_get(
|
||||
self.handle,
|
||||
messages.as_mut_ptr(),
|
||||
&mut message_count,
|
||||
timeout_ms,
|
||||
)
|
||||
};
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
messages.resize(message_count as usize, std::ptr::null_mut());
|
||||
Ok(messages)
|
||||
}
|
||||
|
||||
pub fn device_messages_transmit(&self, messages: Vec<*mut icsneoc2_message_t>) -> Result<u32> {
|
||||
let mut messages_count: u32 = messages.len() as u32;
|
||||
let mut messages = messages;
|
||||
let res: icsneoc2_error_t = unsafe {
|
||||
ffi::icsneoc2_device_messages_transmit(
|
||||
self.handle,
|
||||
messages.as_mut_ptr(),
|
||||
&mut messages_count,
|
||||
)
|
||||
};
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(messages_count)
|
||||
}
|
||||
|
||||
pub fn device_open(&self) -> Result<()> {
|
||||
let res: icsneoc2_error_t = unsafe { ffi::icsneoc2_device_open(self.handle) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn device_open_options_get(&self) -> Result<ffi::icsneoc2_open_options_t> {
|
||||
let mut open_options: ffi::icsneoc2_open_options_t =
|
||||
icsneoc2_open_options_none as ffi::icsneoc2_open_options_t;
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_device_open_options_get(self.handle, &mut open_options) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(open_options)
|
||||
}
|
||||
|
||||
pub fn device_open_options_set(
|
||||
&self,
|
||||
open_options: ffi::icsneoc2_open_options_t,
|
||||
) -> Result<()> {
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_device_open_options_set(self.handle, open_options) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn device_rtc_get(&self) -> Result<i64> {
|
||||
let mut value: i64 = 0;
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_device_rtc_get(self.handle, &mut value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn device_rtc_set(&self, value: i64) -> Result<()> {
|
||||
let res: icsneoc2_error_t = unsafe { ffi::icsneoc2_device_rtc_set(self.handle, value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn device_serial_get(&self) -> Result<String> {
|
||||
// Get the string
|
||||
let mut str: Vec<u8> = vec![0; 255];
|
||||
let mut str_length: u32 = 255;
|
||||
let res = unsafe {
|
||||
icsneoc2_device_serial_get(self.handle, str.as_mut_ptr() as *mut i8, &mut str_length)
|
||||
};
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
// Convert the vec to an String
|
||||
str.resize(str_length as usize, 0);
|
||||
let str_string = {
|
||||
CString::new(str)
|
||||
.expect("CString::new failed")
|
||||
.into_string()
|
||||
.expect("CString::new::into_string")
|
||||
};
|
||||
Ok(str_string)
|
||||
}
|
||||
|
||||
pub fn device_supports_tc10(&self) -> Result<bool> {
|
||||
let mut value: bool = false;
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_device_supports_tc10(self.handle, &mut value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn device_timestamp_resolution_get(&self) -> Result<u32> {
|
||||
let mut timestamp_resolution: u32 = 0;
|
||||
let res: icsneoc2_error_t = unsafe {
|
||||
ffi::icsneoc2_device_timestamp_resolution_get(self.handle, &mut timestamp_resolution)
|
||||
};
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(timestamp_resolution)
|
||||
}
|
||||
|
||||
pub fn device_type_from_type(&self, device_type: icsneoc2_devicetype_t) -> Result<String> {
|
||||
// Get the string
|
||||
let mut str: Vec<u8> = vec![0; 255];
|
||||
let mut str_length: u32 = 255;
|
||||
let res = unsafe {
|
||||
icsneoc2_device_type_name_get(
|
||||
device_type,
|
||||
str.as_mut_ptr() as *mut i8,
|
||||
&mut str_length,
|
||||
)
|
||||
};
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
// Convert the vec to an String
|
||||
str.resize(str_length as usize, 0);
|
||||
let str_string = {
|
||||
CString::new(str)
|
||||
.expect("CString::new failed")
|
||||
.into_string()
|
||||
.expect("CString::new::into_string")
|
||||
};
|
||||
Ok(str_string)
|
||||
}
|
||||
|
||||
pub fn device_type_get(&self) -> Result<icsneoc2_devicetype_t> {
|
||||
let mut value: icsneoc2_devicetype_t = 0;
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_device_type_get(self.handle, &mut value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn error_code_get(error_code: icsneoc2_error_t) -> Error {
|
||||
// Get the error code
|
||||
let mut error_description: Vec<u8> = vec![0; 255];
|
||||
let mut error_description_length: u32 = 255;
|
||||
let res = unsafe {
|
||||
icsneoc2_error_code_get(
|
||||
error_code,
|
||||
error_description.as_mut_ptr() as *mut i8,
|
||||
&mut error_description_length,
|
||||
)
|
||||
};
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Error::APIError(res, "icsneoc2_error_code_get() failed.".to_string());
|
||||
}
|
||||
// Convert the vec to an String
|
||||
error_description.resize(error_description_length as usize, 0);
|
||||
let error_str = CString::new(error_description)
|
||||
.expect("CString::new failed")
|
||||
.into_string()
|
||||
.expect("CString::new::into_string");
|
||||
Error::APIError(error_code, error_str)
|
||||
}
|
||||
|
||||
pub fn event_description_get(&self, event: *mut icsneoc2_event_t) -> Result<String> {
|
||||
// Get the string
|
||||
let mut str: Vec<u8> = vec![0; 255];
|
||||
let mut str_length: u32 = 255;
|
||||
let res = unsafe {
|
||||
icsneoc2_event_description_get(event, str.as_mut_ptr() as *mut i8, &mut str_length)
|
||||
};
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
// Convert the vec to an String
|
||||
str.resize(str_length as usize, 0);
|
||||
let str_string = {
|
||||
CString::new(str)
|
||||
.expect("CString::new failed")
|
||||
.into_string()
|
||||
.expect("CString::new::into_string")
|
||||
};
|
||||
Ok(str_string)
|
||||
}
|
||||
|
||||
pub fn events_get(&self, event_count: u32) -> Result<Vec<*mut icsneoc2_event_t>> {
|
||||
let mut events: Vec<*mut icsneoc2_event_t> =
|
||||
vec![std::ptr::null_mut(); event_count as usize];
|
||||
let mut event_count: u32 = event_count;
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_events_get(events.as_mut_ptr(), &mut event_count) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
events.resize(event_count as usize, std::ptr::null_mut());
|
||||
Ok(events)
|
||||
}
|
||||
|
||||
pub fn message_bus_type_get(
|
||||
&self,
|
||||
message: *mut icsneoc2_message_t,
|
||||
) -> Result<icsneoc2_msg_bus_type_t> {
|
||||
let mut value: icsneoc2_msg_bus_type_t = 0;
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_message_bus_type_get(self.handle, message, &mut value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn message_can_arbid_get(&self, message: *mut icsneoc2_message_t) -> Result<u32> {
|
||||
let mut value: u32 = 0;
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_message_can_arbid_get(self.handle, message, &mut value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn message_can_arbid_set(
|
||||
&self,
|
||||
message: *mut icsneoc2_message_t,
|
||||
value: u32,
|
||||
) -> Result<()> {
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_message_can_arbid_set(self.handle, message, value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn message_can_baudrate_switch_get(
|
||||
&self,
|
||||
message: *mut icsneoc2_message_t,
|
||||
) -> Result<bool> {
|
||||
let mut value: bool = false;
|
||||
let res: icsneoc2_error_t = unsafe {
|
||||
ffi::icsneoc2_message_can_baudrate_switch_get(self.handle, message, &mut value)
|
||||
};
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn message_can_baudrate_switch_set(
|
||||
&self,
|
||||
message: *mut icsneoc2_message_t,
|
||||
value: bool,
|
||||
) -> Result<()> {
|
||||
let res: icsneoc2_error_t = unsafe {
|
||||
ffi::icsneoc2_message_can_baudrate_switch_set(self.handle, message, value)
|
||||
};
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn message_can_canfd_set(
|
||||
&self,
|
||||
message: *mut icsneoc2_message_t,
|
||||
value: bool,
|
||||
) -> Result<()> {
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_message_can_canfd_set(self.handle, message, value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn message_can_create(&self, message_count: u32) -> Result<Vec<*mut icsneoc2_message_t>> {
|
||||
let mut messages: Vec<*mut icsneoc2_message_t> =
|
||||
vec![std::ptr::null_mut(); message_count as usize];
|
||||
let res: icsneoc2_error_t = unsafe {
|
||||
ffi::icsneoc2_message_can_create(self.handle, messages.as_mut_ptr(), message_count)
|
||||
};
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(messages)
|
||||
}
|
||||
|
||||
pub fn message_can_dlc_get(&self, message: *mut icsneoc2_message_t) -> Result<i32> {
|
||||
let mut value: i32 = 0;
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_message_can_dlc_get(self.handle, message, &mut value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn message_can_dlc_set(&self, message: *mut icsneoc2_message_t, value: i32) -> Result<()> {
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_message_can_dlc_set(self.handle, message, value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn message_can_error_state_indicator_get(
|
||||
&self,
|
||||
message: *mut icsneoc2_message_t,
|
||||
) -> Result<bool> {
|
||||
let mut value: bool = false;
|
||||
let res: icsneoc2_error_t = unsafe {
|
||||
ffi::icsneoc2_message_can_error_state_indicator_get(self.handle, message, &mut value)
|
||||
};
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn message_can_extended_set(
|
||||
&self,
|
||||
message: *mut icsneoc2_message_t,
|
||||
value: bool,
|
||||
) -> Result<()> {
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_message_can_extended_set(self.handle, message, value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn message_can_free(&self, message: *mut icsneoc2_message_t) -> Result<()> {
|
||||
let res: icsneoc2_error_t = unsafe { ffi::icsneoc2_message_can_free(self.handle, message) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn message_can_is_canfd(&self, message: *mut icsneoc2_message_t) -> Result<bool> {
|
||||
let mut value: bool = false;
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_message_can_is_canfd(self.handle, message, &mut value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn message_can_is_extended(&self, message: *mut icsneoc2_message_t) -> Result<bool> {
|
||||
let mut value: bool = false;
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_message_can_is_extended(self.handle, message, &mut value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn message_can_is_remote(&self, message: *mut icsneoc2_message_t) -> Result<bool> {
|
||||
let mut value: bool = false;
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_message_can_is_remote(self.handle, message, &mut value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn message_data_get(
|
||||
&self,
|
||||
message: *mut icsneoc2_message_t,
|
||||
data_length: u32,
|
||||
) -> Result<Vec<u8>> {
|
||||
let mut data: Vec<u8> = vec![0; data_length as usize];
|
||||
let mut data_length = data_length;
|
||||
let res: icsneoc2_error_t = unsafe {
|
||||
ffi::icsneoc2_message_data_get(
|
||||
self.handle,
|
||||
message,
|
||||
data.as_mut_ptr(),
|
||||
&mut data_length,
|
||||
)
|
||||
};
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
data.resize(data_length as usize, 0);
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
pub fn message_data_set(&self, message: *mut icsneoc2_message_t, data: Vec<u8>) -> Result<()> {
|
||||
let mut data = data;
|
||||
let res: icsneoc2_error_t = unsafe {
|
||||
ffi::icsneoc2_message_data_set(
|
||||
self.handle,
|
||||
message,
|
||||
data.as_mut_ptr(),
|
||||
data.len() as u32,
|
||||
)
|
||||
};
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn message_is_transmit(&self, message: *mut icsneoc2_message_t) -> Result<bool> {
|
||||
let mut value: bool = false;
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_message_is_transmit(self.handle, message, &mut value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn message_is_valid(&self, message: *mut icsneoc2_message_t) -> Result<bool> {
|
||||
let mut value: bool = false;
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_message_is_valid(self.handle, message, &mut value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn message_netid_get(&self, message: *mut icsneoc2_message_t) -> Result<_icsneoc2_netid_t> {
|
||||
let mut value: icsneoc2_netid_t = 0;
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_message_netid_get(self.handle, message, &mut value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
// TODO: This is gross, there is probably a better way to do this.
|
||||
// TryFrom impl would be a lot of work to implement because there are so many values.
|
||||
// We are relying on the function call to always return a valid value.
|
||||
let value: _icsneoc2_netid_t = unsafe { std::mem::transmute(value as u32) };
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn message_netid_set(
|
||||
&self,
|
||||
message: *mut icsneoc2_message_t,
|
||||
value: _icsneoc2_netid_t,
|
||||
) -> Result<()> {
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_message_netid_set(self.handle, message, value as icsneoc2_netid_t) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn message_type_get(
|
||||
&self,
|
||||
message: *mut icsneoc2_message_t,
|
||||
) -> Result<icsneoc2_msg_type_t> {
|
||||
let mut value: icsneoc2_msg_type_t = 0;
|
||||
let res: icsneoc2_error_t =
|
||||
unsafe { ffi::icsneoc2_message_type_get(self.handle, message, &mut value) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn message_type_name_get(&self, msg_type: icsneoc2_msg_type_t) -> Result<String> {
|
||||
// Get the string
|
||||
let mut str: Vec<u8> = vec![0; 255];
|
||||
let mut str_length: u32 = 255;
|
||||
let res = unsafe {
|
||||
icsneoc2_message_type_name_get(msg_type, str.as_mut_ptr() as *mut i8, &mut str_length)
|
||||
};
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
// Convert the vec to an String
|
||||
str.resize(str_length as usize, 0);
|
||||
let str_string = {
|
||||
CString::new(str)
|
||||
.expect("CString::new failed")
|
||||
.into_string()
|
||||
.expect("CString::new::into_string")
|
||||
};
|
||||
Ok(str_string)
|
||||
}
|
||||
|
||||
pub fn netid_name_get(&self, netid: _icsneoc2_netid_t) -> Result<String> {
|
||||
// Get the string
|
||||
let mut str: Vec<u8> = vec![0; 255];
|
||||
let mut str_length: u32 = 255;
|
||||
let res =
|
||||
unsafe { icsneoc2_netid_name_get(netid as icsneoc2_netid_t, str.as_mut_ptr() as *mut i8, &mut str_length) };
|
||||
// Check the error code
|
||||
if res != icsneoc2_error_success as icsneoc2_error_t {
|
||||
return Err(Self::error_code_get(res));
|
||||
}
|
||||
// Convert the vec to an String
|
||||
str.resize(str_length as usize, 0);
|
||||
let str_string = {
|
||||
CString::new(str)
|
||||
.expect("CString::new failed")
|
||||
.into_string()
|
||||
.expect("CString::new::into_string")
|
||||
};
|
||||
Ok(str_string)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn test_device_find_all() {
|
||||
let devices = Device::find_all(0).unwrap();
|
||||
assert_eq!(devices.len(), 0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user