com.pi4j.plugin.linuxfs.provider.i2c.LinuxFsI2CBus Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of pi4j-plugin-linuxfs Show documentation
Show all versions of pi4j-plugin-linuxfs Show documentation
Pi4J Library Plugin for Linux File System I/O Providers
package com.pi4j.plugin.linuxfs.provider.i2c;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import com.pi4j.exception.Pi4JException;
import com.pi4j.io.i2c.I2C;
import com.pi4j.io.i2c.I2CConfig;
import com.pi4j.library.linuxfs.LinuxFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LinuxFsI2CBus {
public static final long DEFAULT_LOCK_ACQUIRE_TIMEOUT = 1000;
public static final TimeUnit DEFAULT_LOCK_ACQUIRE_TIMEOUT_UNITS = TimeUnit.MILLISECONDS;
private final Integer bus;
protected Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* File handle for this i2c bus
*/
protected LinuxFile file;
private int lastAddress;
protected long lockAquireTimeout;
protected TimeUnit lockAquireTimeoutUnit;
private final ReentrantLock lock = new ReentrantLock(true);
public LinuxFsI2CBus(I2CConfig config) {
this.bus = config.getBus();
final File sysfs = new File("/sys/bus/i2c/devices/i2c-" + this.bus);
if (!sysfs.exists() || !sysfs.isDirectory())
throw new Pi4JException("I2C bus " + this.bus + " does not exist.");
final File devfs = new File("/dev/i2c-" + this.bus);
if (!devfs.exists() || !devfs.canRead() || !devfs.canWrite())
throw new Pi4JException("I2C bus " + this.bus + " does not exist.");
try {
String fileName = devfs.getCanonicalPath();
this.file = new LinuxFile(fileName, "rw");
} catch (IOException e) {
throw new Pi4JException(e);
}
this.lockAquireTimeout = DEFAULT_LOCK_ACQUIRE_TIMEOUT;
this.lockAquireTimeoutUnit = DEFAULT_LOCK_ACQUIRE_TIMEOUT_UNITS;
}
/**
* Selects the slave device if not already selected on this bus. Runs the required ioctl's via JNI.
*
* @param i2c
* Device to select
*/
protected void selectBusSlave(I2C i2c) throws IOException {
if (this.lastAddress == i2c.device())
return;
this.lastAddress = i2c.device();
this.file.ioctl(I2CConstants.I2C_SLAVE, i2c.device() & 0xFF);
}
/**
*
* @param i2c
* @param command From I2CConstants
* @param data values in bytes for all structures, with 4 or 8 byte alignment enforced by filling holes before pointers
* @param offsets ByteBuffer: offsets of pointer/ byte offset of pointedToData
*
* @return 0 if success, else -1
*/
public int executeIOCTL(final I2C i2c, long command, ByteBuffer data, IntBuffer offsets){
int rc = -1;
if (this.lastAddress != i2c.device()) {
this.lastAddress = i2c.device();
}
try {
if (this.lock.tryLock() || this.lock.tryLock(this.lockAquireTimeout, this.lockAquireTimeoutUnit)) {
try {
selectBusSlave(i2c);
this.file.ioctl( command, data, offsets);
rc = 0; //had there been any failure an exception would bypass this statement
} finally {
while (this.lock.isHeldByCurrentThread())
this.lock.unlock();
}
} else {
throw new Pi4JException(
"Failed to get I2C lock on bus " + this.bus + " after " + this.lockAquireTimeout + " "
+ this.lockAquireTimeoutUnit);
}
} catch (InterruptedException e) {
logger.error("Failed locking " + getClass().getSimpleName() + "-" + this.bus, e);
throw new RuntimeException("Could not obtain an access-lock!", e);
} catch (Exception e) {
throw new Pi4JException("Failed to execute action for device " + i2c.device() + " on bus " + this.bus, e);
}
return(rc);
}
public R execute(final I2C i2c, final CheckedFunction action) {
if (i2c == null)
throw new NullPointerException("Parameter 'i2c' is mandatory!");
if (action == null)
throw new NullPointerException("Parameter 'action' is mandatory!");
try {
if (this.lock.tryLock() || this.lock.tryLock(this.lockAquireTimeout, this.lockAquireTimeoutUnit)) {
try {
selectBusSlave(i2c);
return action.apply(this.file);
} finally {
while (this.lock.isHeldByCurrentThread())
this.lock.unlock();
}
} else {
throw new Pi4JException(
"Failed to get I2C lock on bus " + this.bus + " after " + this.lockAquireTimeout + " "
+ this.lockAquireTimeoutUnit);
}
} catch (InterruptedException e) {
logger.error("Failed locking " + getClass().getSimpleName() + "-" + this.bus, e);
throw new RuntimeException("Could not obtain an access-lock!", e);
} catch (Exception e) {
throw new Pi4JException("Failed to execute action for device " + i2c.device() + " on bus " + this.bus, e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy