1use crate::st3215::ST3215;
7use std::ffi::{CStr, CString};
8use std::os::raw::c_char;
9use std::ptr;
10
11pub struct ST3215Handle {
13 inner: ST3215,
14}
15
16#[unsafe(no_mangle)]
24pub extern "C" fn st3215_new(device: *const c_char) -> *mut ST3215Handle {
25 if device.is_null() {
26 return ptr::null_mut();
27 }
28
29 let device_str = unsafe {
30 match CStr::from_ptr(device).to_str() {
31 Ok(s) => s,
32 Err(_) => return ptr::null_mut(),
33 }
34 };
35
36 match ST3215::new(device_str) {
37 Ok(st) => Box::into_raw(Box::new(ST3215Handle { inner: st })),
38 Err(_) => ptr::null_mut(),
39 }
40}
41
42#[unsafe(no_mangle)]
47pub extern "C" fn st3215_free(handle: *mut ST3215Handle) {
48 if !handle.is_null() {
49 unsafe {
50 let _ = Box::from_raw(handle);
51 }
52 }
53}
54
55#[unsafe(no_mangle)]
64pub extern "C" fn st3215_ping_servo(handle: *mut ST3215Handle, servo_id: u8) -> i32 {
65 if handle.is_null() {
66 return 0;
67 }
68
69 let st = unsafe { &(*handle).inner };
70 if st.ping_servo(servo_id) {
71 1
72 } else {
73 0
74 }
75}
76
77#[unsafe(no_mangle)]
87pub extern "C" fn st3215_list_servos(
88 handle: *mut ST3215Handle,
89 out_ids: *mut u8,
90 max_ids: usize,
91) -> usize {
92 if handle.is_null() || out_ids.is_null() {
93 return 0;
94 }
95
96 let st = unsafe { &(*handle).inner };
97 let servos = st.list_servos();
98 let count = servos.len().min(max_ids);
99
100 unsafe {
101 let slice = std::slice::from_raw_parts_mut(out_ids, count);
102 slice.copy_from_slice(&servos[..count]);
103 }
104
105 count
106}
107
108#[unsafe(no_mangle)]
120pub extern "C" fn st3215_move_to(
121 handle: *mut ST3215Handle,
122 servo_id: u8,
123 position: u16,
124 speed: u16,
125 acceleration: u8,
126) -> i32 {
127 if handle.is_null() {
128 return -1;
129 }
130
131 let st = unsafe { &(*handle).inner };
132 match st.move_to(servo_id, position, speed, acceleration, false) {
133 Some(_) => 0,
134 None => -1,
135 }
136}
137
138#[unsafe(no_mangle)]
148pub extern "C" fn st3215_read_position(
149 handle: *mut ST3215Handle,
150 servo_id: u8,
151 out_position: *mut u16,
152) -> i32 {
153 if handle.is_null() || out_position.is_null() {
154 return -1;
155 }
156
157 let st = unsafe { &(*handle).inner };
158 match st.read_position(servo_id) {
159 Some(pos) => {
160 unsafe {
161 *out_position = pos;
162 }
163 0
164 }
165 None => -1,
166 }
167}
168
169#[unsafe(no_mangle)]
179pub extern "C" fn st3215_read_speed(
180 handle: *mut ST3215Handle,
181 servo_id: u8,
182 out_speed: *mut u16,
183) -> i32 {
184 if handle.is_null() || out_speed.is_null() {
185 return -1;
186 }
187
188 let st = unsafe { &(*handle).inner };
189 match st.read_speed(servo_id) {
190 Some(speed) => {
191 unsafe {
192 *out_speed = speed.abs() as u16;
193 }
194 0
195 }
196 None => -1,
197 }
198}
199
200#[unsafe(no_mangle)]
210pub extern "C" fn st3215_read_load(
211 handle: *mut ST3215Handle,
212 servo_id: u8,
213 out_load: *mut f32,
214) -> i32 {
215 if handle.is_null() || out_load.is_null() {
216 return -1;
217 }
218
219 let st = unsafe { &(*handle).inner };
220 match st.read_load(servo_id) {
221 Some(load) => {
222 unsafe {
223 *out_load = load;
224 }
225 0
226 }
227 None => -1,
228 }
229}
230
231#[unsafe(no_mangle)]
241pub extern "C" fn st3215_read_voltage(
242 handle: *mut ST3215Handle,
243 servo_id: u8,
244 out_voltage: *mut f32,
245) -> i32 {
246 if handle.is_null() || out_voltage.is_null() {
247 return -1;
248 }
249
250 let st = unsafe { &(*handle).inner };
251 match st.read_voltage(servo_id) {
252 Some(voltage) => {
253 unsafe {
254 *out_voltage = voltage;
255 }
256 0
257 }
258 None => -1,
259 }
260}
261
262#[unsafe(no_mangle)]
272pub extern "C" fn st3215_read_current(
273 handle: *mut ST3215Handle,
274 servo_id: u8,
275 out_current: *mut f32,
276) -> i32 {
277 if handle.is_null() || out_current.is_null() {
278 return -1;
279 }
280
281 let st = unsafe { &(*handle).inner };
282 match st.read_current(servo_id) {
283 Some(current) => {
284 unsafe {
285 *out_current = current;
286 }
287 0
288 }
289 None => -1,
290 }
291}
292
293#[unsafe(no_mangle)]
303pub extern "C" fn st3215_read_temperature(
304 handle: *mut ST3215Handle,
305 servo_id: u8,
306 out_temperature: *mut u8,
307) -> i32 {
308 if handle.is_null() || out_temperature.is_null() {
309 return -1;
310 }
311
312 let st = unsafe { &(*handle).inner };
313 match st.read_temperature(servo_id) {
314 Some(temp) => {
315 unsafe {
316 *out_temperature = temp;
317 }
318 0
319 }
320 None => -1,
321 }
322}
323
324#[unsafe(no_mangle)]
333pub extern "C" fn st3215_is_moving(handle: *mut ST3215Handle, servo_id: u8) -> i32 {
334 if handle.is_null() {
335 return -1;
336 }
337
338 let st = unsafe { &(*handle).inner };
339 match st.is_moving(servo_id) {
340 Some(true) => 1,
341 Some(false) => 0,
342 None => -1,
343 }
344}
345
346#[unsafe(no_mangle)]
356pub extern "C" fn st3215_enable_torque(
357 handle: *mut ST3215Handle,
358 servo_id: u8,
359 enable: i32,
360) -> i32 {
361 if handle.is_null() {
362 return -1;
363 }
364
365 let st = unsafe { &(*handle).inner };
366 let result = if enable != 0 {
367 st.enable_torque(servo_id)
368 } else {
369 st.disable_torque(servo_id)
370 };
371 match result {
372 Ok(_) => 0,
373 Err(_) => -1,
374 }
375}
376
377#[unsafe(no_mangle)]
382pub extern "C" fn st3215_version() -> *mut c_char {
383 let version = env!("CARGO_PKG_VERSION");
384 match CString::new(version) {
385 Ok(s) => s.into_raw(),
386 Err(_) => ptr::null_mut(),
387 }
388}
389
390#[unsafe(no_mangle)]
395pub extern "C" fn st3215_free_string(s: *mut c_char) {
396 if !s.is_null() {
397 unsafe {
398 let _ = CString::from_raw(s);
399 }
400 }
401}