Skip to content

Commit

Permalink
Merge #68
Browse files Browse the repository at this point in the history
68: Allow forcefully setting slave address r=eldruin a=iamkroot

Closes #59

I think a few more warnings are needed in the docstrings.
Should the contents of the two `new` constructors be abstracted into a separate method?

Co-authored-by: iamkroot <kroot.patel@gmail.com>
Co-authored-by: Diego Barrios Romero <eldruin@gmail.com>
  • Loading branch information
3 people authored Nov 16, 2021
2 parents a0f71ff + c70d87a commit 1c2c672
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Versioning](https://semver.org/spec/v2.0.0.html).

- Updated nix to allow both version `0.22` or `0.23`.
- Add PEC support for SMBus compatible adapters
- Add `LinuxI2CDevice::force_new()` to open the device without checking if the address is bound to a driver.

## [v0.5.0] - 2021-09-21

Expand Down
10 changes: 9 additions & 1 deletion src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,10 @@ pub struct i2c_rdwr_ioctl_data {
mod ioctl {
pub use super::i2c_rdwr_ioctl_data;
pub use super::i2c_smbus_ioctl_data;
use super::{I2C_PEC, I2C_RDWR, I2C_SLAVE, I2C_SMBUS};
use super::{I2C_PEC, I2C_RDWR, I2C_SLAVE, I2C_SLAVE_FORCE, I2C_SMBUS};

ioctl_write_int_bad!(set_i2c_slave_address, I2C_SLAVE);
ioctl_write_int_bad!(set_i2c_slave_address_force, I2C_SLAVE_FORCE);
ioctl_write_int_bad!(set_smbus_pec, I2C_PEC);
ioctl_write_ptr_bad!(i2c_smbus, I2C_SMBUS, i2c_smbus_ioctl_data);
ioctl_write_ptr_bad!(i2c_rdwr, I2C_RDWR, i2c_rdwr_ioctl_data);
Expand All @@ -168,6 +169,13 @@ pub fn i2c_set_slave_address(fd: RawFd, slave_address: u16) -> Result<(), nix::E
Ok(())
}

pub fn i2c_set_slave_address_force(fd: RawFd, slave_address: u16) -> Result<(), nix::Error> {
unsafe {
ioctl::set_i2c_slave_address_force(fd, i32::from(slave_address))?;
}
Ok(())
}

pub fn i2c_set_smbus_pec(fd: RawFd, enable: bool) -> Result<(), nix::Error> {
unsafe {
ioctl::set_smbus_pec(fd, i32::from(enable))?;
Expand Down
31 changes: 31 additions & 0 deletions src/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,27 @@ impl LinuxI2CDevice {
Ok(device)
}

/// Create a new I2CDevice for the specified path, without checking if the
/// device is bound to a driver
///
/// # Safety
/// Using this can seriously confuse the original driver, and may cause all
/// future communication to perform the wrong operations and/or return wrong results.
pub unsafe fn force_new<P: AsRef<Path>>(
path: P,
slave_address: u16,
) -> Result<LinuxI2CDevice, LinuxI2CError> {
let file = OpenOptions::new().read(true).write(true).open(path)?;
let mut device = LinuxI2CDevice {
devfile: file,
slave_address: 0, // will be set later
pec: false,
};
device.force_set_slave_address(slave_address)?;
device.set_smbus_pec(false)?;
Ok(device)
}

/// Set the slave address for this device
///
/// Typically the address is expected to be 7-bits but 10-bit addresses
Expand All @@ -127,6 +148,16 @@ impl LinuxI2CDevice {
Ok(())
}

/// Set the slave address for this device, even if it is already in use
/// by a driver
///
/// This is private; use `force_new` instead.
unsafe fn force_set_slave_address(&mut self, slave_address: u16) -> Result<(), LinuxI2CError> {
ffi::i2c_set_slave_address_force(self.as_raw_fd(), slave_address)?;
self.slave_address = slave_address;
Ok(())
}

/// Enable/Disable PEC support for this device
///
/// Used only for SMBus transactions. This request only has an effect if the
Expand Down

0 comments on commit 1c2c672

Please sign in to comment.