use crate::i2c::{Const, I2c};
use i2cdev::core::I2CDevice;
use mlua::{Error::RuntimeError, FromLua, Lua, MultiValue, Table, prelude::LuaError};
#[cfg(not(all(target_os = "linux", any(target_arch = "arm", target_arch = "aarch64"))))]
pub(super) fn handle(_lua: &Lua, _i2c: &I2c, _args: MultiValue) -> Result<(), LuaError> {
Err(RuntimeError("I²C is unsupported on this device".to_string()))
}
#[cfg(all(target_os = "linux", any(target_arch = "arm", target_arch = "aarch64")))]
pub(super) fn handle(lua: &Lua, i2c: &I2c, args: MultiValue) -> Result<(), LuaError> {
use i2cdev::linux::LinuxI2CDevice;
let addr: u16 = u16::from_lua(args[0].clone(), lua)?;
let messages: Table = Table::from_lua(args[1].clone(), lua)?;
let mut i2cdev = LinuxI2CDevice::new(i2c.device.clone(), addr).map_err(|err| RuntimeError(err.to_string()))?;
transfer_(lua, i2c, &mut i2cdev, &messages)
}
#[allow(dead_code)]
fn transfer_<T: I2CDevice + Sized>(lua: &Lua, _i2c: &I2c, i2cdev: &mut T, messages: &Table) -> Result<(), LuaError> {
for i in 1..=messages.len()? as usize {
let message: Table = messages.get(i)?;
let msg_len: usize = message.len()? as usize;
let msg_flags: u16 = match message.get("flags") {
Ok(flags) => {
message.raw_remove("flags")?;
u16::from_lua(flags, lua)?
}
Err(_) => 0,
};
if msg_flags & Const::Rd as u16 > 0 {
for i in 1..=msg_len {
let c = i2cdev.smbus_read_byte().map_err(|err| RuntimeError(err.to_string()))?;
message.raw_set(i, c)?;
}
} else {
let mut data = vec![0_u8; msg_len];
for (i, item) in data.iter_mut().enumerate().take(msg_len) {
*item = u8::from_lua(message.get(i + 1)?, lua)?;
}
i2cdev
.smbus_write_block_data(0x01, &data)
.map_err(|err| RuntimeError(err.to_string()))?;
}
}
Ok(())
}