pub mod memory_map;
use crate::{error::Error, Device};
use memory_map::*;
use nix::fcntl::{open, OFlag}; use nix::sys::stat::Mode;
use nix::unistd::close;
use nix::{ioctl_read_bad, ioctl_write_ptr_bad};
ioctl_read_bad!(ioctl_read, ioctl_code::READ, [u8]);
ioctl_write_ptr_bad!(ioctl_write, ioctl_code::WRITE, [u8]);
#[derive(Debug)]
pub struct Bus {
pub device_file: &'static str,
pub regmap_fd: std::os::unix::io::RawFd,
pub device_name: Device,
pub device_version: u32,
pub device_leds: u8,
pub fpga_frequency: u32,
}
impl Bus {
pub fn init() -> Result<Bus, Error> {
let mut bus = Bus {
device_file: "/dev/matrixio_regmap",
regmap_fd: 0,
device_name: Device::Unknown,
device_version: 0,
device_leds: 0,
fpga_frequency: 0,
};
bus.regmap_fd = open(bus.device_file, OFlag::O_RDWR, Mode::empty())?;
let (name, version) = bus.get_device_info()?;
bus.device_name = name;
bus.device_version = version;
bus.device_leds = match bus.device_name {
Device::Creator => device_info::MATRIX_CREATOR_LEDS,
Device::Voice => device_info::MATRIX_VOICE_LEDS,
_ => panic!("Cannot determine number of LEDs on device (This is a hard-coded value)."),
};
bus.fpga_frequency = bus.get_fpga_frequency()?;
println!("{:?}", bus);
Ok(bus)
}
pub fn write(&self, write_buffer: &mut [u8]) {
unsafe {
ioctl_write(self.regmap_fd, write_buffer).expect("error in IOCTL WRITE");
}
}
pub fn read(&self, read_buffer: &mut [u8]) {
unsafe {
ioctl_read(self.regmap_fd, read_buffer).expect("error in IOCTL READ");
}
}
pub fn close(&self) {
close(self.regmap_fd).unwrap();
}
fn get_device_info(&self) -> Result<(Device, u32), Error> {
let mut data: [i32; 4] = [0; 4];
data[0] = fpga_address::CONF as i32;
data[1] = 8;
self.read(unsafe { std::mem::transmute::<&mut [i32], &mut [u8]>(&mut data) });
let device_name = data[2];
let device_version = data[3];
Ok((
match device_name {
device_info::MATRIX_CREATOR => Device::Creator,
device_info::MATRIX_VOICE => Device::Voice,
_ => return Err(Error::UnknownDevice),
},
device_version as u32,
))
}
fn get_fpga_frequency(&self) -> Result<u32, Error> {
let mut data: [i32; 3] = [0; 3];
data[0] = (fpga_address::CONF + 4) as i32;
data[1] = 4;
self.read(unsafe { std::mem::transmute::<&mut [i32], &mut [u8]>(&mut data) });
let value0 = data[2] >> 16; let value1 = !(value0 << 16) & data[2]; let frequency = (device_info::FPGA_CLOCK * value0 as u32) / value1 as u32;
Ok(frequency)
}
}