use embedded_hal::blocking::delay::DelayMs;
use embedded_hal::blocking::spi::{Transfer, Write};
use embedded_hal::digital::v2::OutputPin;
use crate::wrapper::Wrapper;
use crate::Transactional;
pub trait Cursed {}
pub trait Conv {
fn to_c_ptr(&mut self) -> *mut libc::c_void;
fn from_c_ptr<'a>(ctx: *mut libc::c_void) -> &'a mut Self;
}
impl<T> Conv for T
where
T: Cursed,
{
fn to_c_ptr(&mut self) -> *mut libc::c_void {
self as *mut Self as *mut libc::c_void
}
fn from_c_ptr<'a>(ctx: *mut libc::c_void) -> &'a mut Self {
unsafe {
let s = ctx as *mut Self;
&mut *s
}
}
}
impl<Spi, SpiError, CsPin, BusyPin, ReadyPin, ResetPin, PinError, Delay> Cursed
for Wrapper<Spi, SpiError, CsPin, BusyPin, ReadyPin, ResetPin, PinError, Delay>
{
}
impl<Spi, SpiError, CsPin, BusyPin, ReadyPin, ResetPin, PinError, Delay>
Wrapper<Spi, SpiError, CsPin, BusyPin, ReadyPin, ResetPin, PinError, Delay>
where
Spi: Transfer<u8, Error = SpiError> + Write<u8, Error = SpiError>,
CsPin: OutputPin<Error = PinError>,
Delay: DelayMs<u32>,
{
pub extern "C" fn ffi_spi_write(
ctx: *mut libc::c_void,
prefix: *mut u8,
prefix_len: u16,
data: *mut u8,
data_len: u16,
) -> isize {
let s = Self::from_c_ptr(ctx);
let prefix: &[u8] = unsafe { core::slice::from_raw_parts(prefix, prefix_len as usize) };
let data: &[u8] = unsafe { core::slice::from_raw_parts(data, data_len as usize) };
match s.spi_write(&prefix, &data) {
Ok(_) => 0,
Err(e) => {
s.err = Some(e);
-1
}
}
}
pub extern "C" fn ffi_spi_read(
ctx: *mut libc::c_void,
prefix: *mut u8,
prefix_len: u16,
data: *mut u8,
data_len: u16,
) -> isize {
let s = Self::from_c_ptr(ctx);
let prefix: &[u8] = unsafe { core::slice::from_raw_parts(prefix, prefix_len as usize) };
let mut data: &mut [u8] =
unsafe { core::slice::from_raw_parts_mut(data, data_len as usize) };
match s.spi_read(&prefix, &mut data) {
Ok(_) => 0,
Err(e) => {
s.err = Some(e);
-1
}
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[derive(Debug, PartialEq)]
struct Something(bool);
impl Cursed for Something {}
#[test]
fn test_compat() {
let mut s = Something(true);
let p = s.to_c_ptr();
let r = Something::from_c_ptr(p);
assert_eq!(&s, r);
}
}