#![allow(clippy::missing_safety_doc)]
use crate::{Frame, Interface};
#[repr(C)]
pub struct CFrame {
channel: u8,
id: u32,
dlc: u8,
data: [u8; 64],
ext: u8,
fd: u8,
brs: u8,
esi: u8,
loopback: u8,
rtr: u8,
err: u8,
}
impl CFrame {
fn from_frame(f: Frame) -> CFrame {
CFrame {
channel: f.channel,
id: f.can_id,
dlc: f.can_dlc,
data: f.data_as_array(),
ext: if f.ext { 1 } else { 0 },
fd: if f.fd { 1 } else { 0 },
brs: if f.brs { 1 } else { 0 },
esi: if f.esi { 1 } else { 0 },
loopback: if f.loopback { 1 } else { 0 },
rtr: if f.rtr { 1 } else { 0 },
err: if f.err { 1 } else { 0 },
}
}
}
#[repr(C)]
pub struct CInterface {
i: Option<Interface>,
c_rx_cb: Option<extern "C" fn(*const CFrame)>,
}
#[no_mangle]
pub extern "C" fn cantact_init() -> *mut CInterface {
Box::into_raw(Box::new(CInterface {
i: None,
c_rx_cb: None,
}))
}
#[no_mangle]
pub unsafe extern "C" fn cantact_deinit(ptr: *mut CInterface) -> i32 {
Box::from_raw(ptr);
0
}
#[no_mangle]
pub unsafe extern "C" fn cantact_set_rx_callback(
ptr: *mut CInterface,
cb: Option<extern "C" fn(*const CFrame)>,
) -> i32 {
let mut ci = &mut *ptr;
ci.c_rx_cb = cb;
0
}
#[no_mangle]
pub unsafe extern "C" fn cantact_open(ptr: *mut CInterface) -> i32 {
let i = match Interface::new() {
Ok(i) => i,
Err(_) => return -1,
};
let ci = &mut *ptr;
ci.i = Some(i);
0
}
#[no_mangle]
pub unsafe extern "C" fn cantact_close(ptr: *mut CInterface) -> i32 {
let mut ci = &mut *ptr;
ci.i = None;
0
}
#[no_mangle]
pub unsafe extern "C" fn cantact_start(ptr: *mut CInterface) -> i32 {
let ci = &mut *ptr;
let cb = ci.c_rx_cb;
match &mut ci.i {
Some(i) => i
.start(move |f: Frame| {
match cb {
None => {}
Some(cb) => {
cb(&CFrame::from_frame(f));
}
};
})
.expect("failed to start device"),
None => return -1,
};
0
}
#[no_mangle]
pub unsafe extern "C" fn cantact_stop(ptr: *mut CInterface) -> i32 {
let ci = &mut *ptr;
match &mut ci.i {
Some(i) => i.stop().expect("failed to stop device"),
None => return -1,
}
0
}
#[no_mangle]
pub unsafe extern "C" fn cantact_transmit(ptr: *mut CInterface, cf: CFrame) -> i32 {
let ci = &mut *ptr;
let f = Frame {
channel: 0, can_id: cf.id,
can_dlc: cf.dlc,
data: cf.data.to_vec(),
ext: cf.ext > 0,
fd: cf.fd > 0,
brs: cf.brs > 0,
esi: cf.esi > 0,
loopback: false,
rtr: cf.rtr > 0,
err: cf.err > 0,
timestamp: None,
};
match &mut ci.i {
Some(i) => i.send(f).expect("failed to transmit frame"),
None => return -1,
};
0
}
#[no_mangle]
pub unsafe extern "C" fn cantact_set_bitrate(
ptr: *mut CInterface,
channel: u8,
bitrate: u32,
) -> i32 {
let ci = &mut *ptr;
match &mut ci.i {
Some(i) => i
.set_bitrate(channel as usize, bitrate)
.expect("failed to set bitrate"),
None => return -1,
}
0
}
#[no_mangle]
pub unsafe extern "C" fn cantact_set_enabled(
ptr: *mut CInterface,
channel: u8,
enabled: u8,
) -> i32 {
let ci = &mut *ptr;
match &mut ci.i {
Some(i) => i
.set_enabled(channel as usize, enabled > 0)
.expect("failed to enable channel"),
None => return -1,
}
0
}
#[no_mangle]
pub unsafe extern "C" fn cantact_set_monitor(
ptr: *mut CInterface,
channel: u8,
enabled: u8,
) -> i32 {
let ci = &mut *ptr;
match &mut ci.i {
Some(i) => i
.set_monitor(channel as usize, enabled > 0)
.expect("failed to set monitoring mode"),
None => return -1,
}
0
}
#[no_mangle]
pub unsafe extern "C" fn cantact_set_hw_loopback(
ptr: *mut CInterface,
channel: u8,
enabled: u8,
) -> i32 {
let ci = &mut *ptr;
match &mut ci.i {
Some(i) => i
.set_loopback(channel as usize, enabled > 0)
.expect("failed to enable channel"),
None => return -1,
}
0
}
#[no_mangle]
pub unsafe extern "C" fn cantact_get_channel_count(ptr: *mut CInterface) -> i32 {
let ci = &mut *ptr;
match &mut ci.i {
Some(i) => i.channels() as i32,
None => -1,
}
}