use i2c::{Address, BulkTransfer};
use serial_test::serial;
use std::io::{Read, Write};
use crate::{Error, I2c};
#[test]
#[serial(device)]
pub fn test_connect() {
I2c::open_single_device().unwrap();
}
#[test]
#[serial(device)]
pub fn test_nack() {
use i2c::Message;
let mut bus = I2c::open_single_device().unwrap();
let mut read_buf = [0u8; 2];
let read_res = bus.i2c_transfer(&mut [Message::Read {
address: 0x03,
data: &mut read_buf,
flags: Default::default(),
}]);
assert_eq!(read_res, Err(Error::Nack));
let write_res = bus.i2c_transfer(&mut [Message::Write {
address: 0x03,
data: &[0, 1, 2, 3],
flags: Default::default(),
}]);
assert_eq!(write_res, Err(Error::Nack));
}
#[test]
#[serial(device)]
pub fn test_nack_std_io() {
let mut bus = I2c::open_single_device().unwrap();
bus.set_slave_address(0x03, false).unwrap();
let mut read_buf = [0u8; 2];
let read_res = bus.read(&mut read_buf);
assert_eq!(
read_res.err().unwrap().kind(),
std::io::ErrorKind::NotConnected
);
let write_res = bus.write(&[0, 1, 2, 3]);
assert_eq!(
write_res.err().unwrap().kind(),
std::io::ErrorKind::NotConnected
);
}
#[test]
#[serial(device)]
pub fn test_general_call() {
use i2c::Message;
let mut bus = I2c::open_single_device().unwrap();
let mut read_buf = [];
let read_res = bus.i2c_transfer(&mut [Message::Read {
address: 0x00,
data: &mut read_buf,
flags: Default::default(),
}]);
assert!(read_res.is_ok());
bus.set_slave_address(0x00, false).unwrap();
let mut read_buf = [];
let read_res = bus.read(&mut read_buf);
assert!(read_res.is_ok());
}
const EEPROM_TEST_PATTERN: [u8; 16] = [
0xaa, 0x55, 0xa0, 0xa5, 0x0a, 0x5a, 0xff, 0x00, 0x12, 0xca, 0xff, 0xee, 0x12, 0x23, 0x34, 0x45,
];
#[cfg(feature = "hw-tests-program-eeprom")]
fn pre_program_eeprom(bus: &mut I2c<impl rusb::UsbContext>) {
use i2c::Message;
let mut data = [0u8; 17];
data[0] = 0x20;
data[1..].copy_from_slice(&EEPROM_TEST_PATTERN);
bus.i2c_transfer(&mut [Message::Write {
address: 0x50,
data: &data,
flags: Default::default(),
}])
.unwrap();
}
#[test]
#[serial(device)]
pub fn test_eeprom_read() {
use i2c::Message;
let mut bus = I2c::open_single_device().unwrap();
#[cfg(feature = "hw-tests-program-eeprom")]
pre_program_eeprom(&mut bus);
let mut read_buf = [0u8; 0x40];
for off in &[0x00, 0x20] {
bus.i2c_transfer(&mut [
Message::Write {
address: 0x50,
data: &[0x20 - 8],
flags: Default::default(),
},
Message::Read {
address: 0x50,
data: &mut read_buf[*off..*off + 0x20],
flags: Default::default(),
},
])
.unwrap();
}
assert_eq!(&read_buf[8..24], &EEPROM_TEST_PATTERN);
assert_eq!(&read_buf[0x20 + 8..0x20 + 24], &EEPROM_TEST_PATTERN);
assert_eq!(&read_buf[..0x20], &read_buf[0x20..]);
}
#[test]
#[serial(device)]
#[ignore] pub fn test_error_recovery() {
fn check_valid_read(bus: &mut I2c<impl rusb::UsbContext>) {
let mut buf = [0u8; 16];
bus.write_all(&[0x20]).unwrap();
bus.read_exact(&mut buf).unwrap();
assert_eq!(&buf, &EEPROM_TEST_PATTERN);
}
let mut bus = I2c::open_single_device().unwrap();
{
#[cfg(feature = "hw-tests-program-eeprom")]
pre_program_eeprom(&mut bus);
}
bus.set_slave_address(0x50, false).unwrap();
check_valid_read(&mut bus);
bus.set_slave_address(0x03, false).unwrap();
assert!(bus.write_all(&[0]).is_err());
bus.set_slave_address(0x50, false).unwrap();
check_valid_read(&mut bus);
let mut big_buf = [0u8; 256];
bus.write_all(&[0u8]).unwrap();
assert!(bus.read_exact(&mut big_buf[..128]).is_err());
check_valid_read(&mut bus);
assert!(bus.read_exact(&mut big_buf[..256]).is_err());
check_valid_read(&mut bus);
}
#[test]
#[serial(device)]
pub fn test_eeprom_big_reads() {
let mut bus = I2c::open_single_device().unwrap();
let mut buf = [0u8; 256];
#[cfg(feature = "hw-tests-program-eeprom")]
pre_program_eeprom(&mut bus);
const MAX_READ: usize = 101;
for size in 16..=MAX_READ {
bus.set_slave_address(0x50, false).unwrap();
bus.write_all(&[0x20]).unwrap();
bus.read_exact(&mut buf[..size]).unwrap();
assert_eq!(&buf[..16], &EEPROM_TEST_PATTERN);
}
}