use crate::st3215::ST3215;
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
use std::ptr;
pub struct ST3215Handle {
inner: ST3215,
}
#[unsafe(no_mangle)]
pub extern "C" fn st3215_new(device: *const c_char) -> *mut ST3215Handle {
if device.is_null() {
return ptr::null_mut();
}
let device_str = unsafe {
match CStr::from_ptr(device).to_str() {
Ok(s) => s,
Err(_) => return ptr::null_mut(),
}
};
match ST3215::new(device_str) {
Ok(st) => Box::into_raw(Box::new(ST3215Handle { inner: st })),
Err(_) => ptr::null_mut(),
}
}
#[unsafe(no_mangle)]
pub extern "C" fn st3215_free(handle: *mut ST3215Handle) {
if !handle.is_null() {
unsafe {
let _ = Box::from_raw(handle);
}
}
}
#[unsafe(no_mangle)]
pub extern "C" fn st3215_ping_servo(handle: *mut ST3215Handle, servo_id: u8) -> i32 {
if handle.is_null() {
return 0;
}
let st = unsafe { &(*handle).inner };
if st.ping_servo(servo_id) {
1
} else {
0
}
}
#[unsafe(no_mangle)]
pub extern "C" fn st3215_list_servos(
handle: *mut ST3215Handle,
out_ids: *mut u8,
max_ids: usize,
) -> usize {
if handle.is_null() || out_ids.is_null() {
return 0;
}
let st = unsafe { &(*handle).inner };
let servos = st.list_servos();
let count = servos.len().min(max_ids);
unsafe {
let slice = std::slice::from_raw_parts_mut(out_ids, count);
slice.copy_from_slice(&servos[..count]);
}
count
}
#[unsafe(no_mangle)]
pub extern "C" fn st3215_move_to(
handle: *mut ST3215Handle,
servo_id: u8,
position: u16,
speed: u16,
acceleration: u8,
) -> i32 {
if handle.is_null() {
return -1;
}
let st = unsafe { &(*handle).inner };
match st.move_to(servo_id, position, speed, acceleration, false) {
Some(_) => 0,
None => -1,
}
}
#[unsafe(no_mangle)]
pub extern "C" fn st3215_read_position(
handle: *mut ST3215Handle,
servo_id: u8,
out_position: *mut u16,
) -> i32 {
if handle.is_null() || out_position.is_null() {
return -1;
}
let st = unsafe { &(*handle).inner };
match st.read_position(servo_id) {
Some(pos) => {
unsafe {
*out_position = pos;
}
0
}
None => -1,
}
}
#[unsafe(no_mangle)]
pub extern "C" fn st3215_read_speed(
handle: *mut ST3215Handle,
servo_id: u8,
out_speed: *mut u16,
) -> i32 {
if handle.is_null() || out_speed.is_null() {
return -1;
}
let st = unsafe { &(*handle).inner };
match st.read_speed(servo_id) {
Some(speed) => {
unsafe {
*out_speed = speed.abs() as u16;
}
0
}
None => -1,
}
}
#[unsafe(no_mangle)]
pub extern "C" fn st3215_read_load(
handle: *mut ST3215Handle,
servo_id: u8,
out_load: *mut f32,
) -> i32 {
if handle.is_null() || out_load.is_null() {
return -1;
}
let st = unsafe { &(*handle).inner };
match st.read_load(servo_id) {
Some(load) => {
unsafe {
*out_load = load;
}
0
}
None => -1,
}
}
#[unsafe(no_mangle)]
pub extern "C" fn st3215_read_voltage(
handle: *mut ST3215Handle,
servo_id: u8,
out_voltage: *mut f32,
) -> i32 {
if handle.is_null() || out_voltage.is_null() {
return -1;
}
let st = unsafe { &(*handle).inner };
match st.read_voltage(servo_id) {
Some(voltage) => {
unsafe {
*out_voltage = voltage;
}
0
}
None => -1,
}
}
#[unsafe(no_mangle)]
pub extern "C" fn st3215_read_current(
handle: *mut ST3215Handle,
servo_id: u8,
out_current: *mut f32,
) -> i32 {
if handle.is_null() || out_current.is_null() {
return -1;
}
let st = unsafe { &(*handle).inner };
match st.read_current(servo_id) {
Some(current) => {
unsafe {
*out_current = current;
}
0
}
None => -1,
}
}
#[unsafe(no_mangle)]
pub extern "C" fn st3215_read_temperature(
handle: *mut ST3215Handle,
servo_id: u8,
out_temperature: *mut u8,
) -> i32 {
if handle.is_null() || out_temperature.is_null() {
return -1;
}
let st = unsafe { &(*handle).inner };
match st.read_temperature(servo_id) {
Some(temp) => {
unsafe {
*out_temperature = temp;
}
0
}
None => -1,
}
}
#[unsafe(no_mangle)]
pub extern "C" fn st3215_is_moving(handle: *mut ST3215Handle, servo_id: u8) -> i32 {
if handle.is_null() {
return -1;
}
let st = unsafe { &(*handle).inner };
match st.is_moving(servo_id) {
Some(true) => 1,
Some(false) => 0,
None => -1,
}
}
#[unsafe(no_mangle)]
pub extern "C" fn st3215_enable_torque(
handle: *mut ST3215Handle,
servo_id: u8,
enable: i32,
) -> i32 {
if handle.is_null() {
return -1;
}
let st = unsafe { &(*handle).inner };
let result = if enable != 0 {
st.enable_torque(servo_id)
} else {
st.disable_torque(servo_id)
};
match result {
Ok(_) => 0,
Err(_) => -1,
}
}
#[unsafe(no_mangle)]
pub extern "C" fn st3215_version() -> *mut c_char {
let version = env!("CARGO_PKG_VERSION");
match CString::new(version) {
Ok(s) => s.into_raw(),
Err(_) => ptr::null_mut(),
}
}
#[unsafe(no_mangle)]
pub extern "C" fn st3215_free_string(s: *mut c_char) {
if !s.is_null() {
unsafe {
let _ = CString::from_raw(s);
}
}
}