Skip to content

Commit 1c2c672

Browse files
bors[bot]iamkrooteldruin
authored
Merge #68
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 <[email protected]> Co-authored-by: Diego Barrios Romero <[email protected]>
2 parents a0f71ff + c70d87a commit 1c2c672

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Versioning](https://semver.org/spec/v2.0.0.html).
1010

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

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

src/ffi.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,10 @@ pub struct i2c_rdwr_ioctl_data {
153153
mod ioctl {
154154
pub use super::i2c_rdwr_ioctl_data;
155155
pub use super::i2c_smbus_ioctl_data;
156-
use super::{I2C_PEC, I2C_RDWR, I2C_SLAVE, I2C_SMBUS};
156+
use super::{I2C_PEC, I2C_RDWR, I2C_SLAVE, I2C_SLAVE_FORCE, I2C_SMBUS};
157157

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

172+
pub fn i2c_set_slave_address_force(fd: RawFd, slave_address: u16) -> Result<(), nix::Error> {
173+
unsafe {
174+
ioctl::set_i2c_slave_address_force(fd, i32::from(slave_address))?;
175+
}
176+
Ok(())
177+
}
178+
171179
pub fn i2c_set_smbus_pec(fd: RawFd, enable: bool) -> Result<(), nix::Error> {
172180
unsafe {
173181
ioctl::set_smbus_pec(fd, i32::from(enable))?;

src/linux.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,27 @@ impl LinuxI2CDevice {
110110
Ok(device)
111111
}
112112

113+
/// Create a new I2CDevice for the specified path, without checking if the
114+
/// device is bound to a driver
115+
///
116+
/// # Safety
117+
/// Using this can seriously confuse the original driver, and may cause all
118+
/// future communication to perform the wrong operations and/or return wrong results.
119+
pub unsafe fn force_new<P: AsRef<Path>>(
120+
path: P,
121+
slave_address: u16,
122+
) -> Result<LinuxI2CDevice, LinuxI2CError> {
123+
let file = OpenOptions::new().read(true).write(true).open(path)?;
124+
let mut device = LinuxI2CDevice {
125+
devfile: file,
126+
slave_address: 0, // will be set later
127+
pec: false,
128+
};
129+
device.force_set_slave_address(slave_address)?;
130+
device.set_smbus_pec(false)?;
131+
Ok(device)
132+
}
133+
113134
/// Set the slave address for this device
114135
///
115136
/// Typically the address is expected to be 7-bits but 10-bit addresses
@@ -127,6 +148,16 @@ impl LinuxI2CDevice {
127148
Ok(())
128149
}
129150

151+
/// Set the slave address for this device, even if it is already in use
152+
/// by a driver
153+
///
154+
/// This is private; use `force_new` instead.
155+
unsafe fn force_set_slave_address(&mut self, slave_address: u16) -> Result<(), LinuxI2CError> {
156+
ffi::i2c_set_slave_address_force(self.as_raw_fd(), slave_address)?;
157+
self.slave_address = slave_address;
158+
Ok(())
159+
}
160+
130161
/// Enable/Disable PEC support for this device
131162
///
132163
/// Used only for SMBus transactions. This request only has an effect if the

0 commit comments

Comments
 (0)