Beispiel #1
0
int I2C::endTransaction()
{
	if (!transactionState)
	{
		iooo_error(
				"I2C::endTransaction() warning: There is no currently active transaction.\n");
		return 0;
	}

	if (!isReady())
		return -1;

	transactionState = false;

	struct i2c_rdwr_ioctl_data msgset;

	msgset.nmsgs = msgs.size();
	msgset.msgs = &msgs[0];

	if (ioctl(fd, I2C_RDWR, &msgset) < 0)
	{
		iooo_error("I2C::endTransaction() error: %s (%d)\n", strerror(errno), errno);
		msgs.clear();
		return -1;
	}

	msgs.clear();
	return 0;
}
Beispiel #2
0
Datei: SPI.cpp Projekt: CJxD/IOoo
int SPI::setSpeed(uint32_t speed)
{
	if (resources == nullptr)
	{
		iooo_error("SPI::setSpeed(): failed - no device has been opened\n");
		return -EDESTADDRREQ;
	}

	std::lock_guard<std::recursive_mutex> lock(resources->rwlock);

	int r;
	if (!isReady())
		return -ENODEV;
	r = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
	if (r < 0)
	{
		iooo_error("ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed): %s", strerror(r));
		return r;
	}

	uint32_t tmp;
	r = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &tmp);
	if (r < 0)
	{
		iooo_error("ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed): %s", strerror(r));
		return r;
	}
	this->speed = tmp;
	return 1;

}
Beispiel #3
0
Datei: SPI.cpp Projekt: CJxD/IOoo
int SPI::xfer1(const void *wbuf, void *rbuf, int len)
{
	if (resources == nullptr)
	{
		iooo_error("SPI::xfer1(): failed - no device has been opened\n");
		return -EDESTADDRREQ;
	}

	std::lock_guard<std::recursive_mutex> lock(resources->rwlock);

	struct spi_ioc_transfer txinfo;
	txinfo.tx_buf = (__u64 ) wbuf;
	txinfo.rx_buf = (__u64 ) rbuf;
	txinfo.len = len;
	txinfo.delay_usecs = 0;
	txinfo.speed_hz = speed;
	txinfo.bits_per_word = bpw;
	txinfo.cs_change = 0;

	int r = ioctl(fd, SPI_IOC_MESSAGE(1), &txinfo);
	if (r < 0)
	{
		iooo_error("ioctl(fd, SPI_IOC_MESSAGE(1), &txinfo): %s (len=%d)\n",
				strerror(r), len);
		return r;
	}

	return len;
}
Beispiel #4
0
Datei: SPI.cpp Projekt: CJxD/IOoo
int SPI::setMode(uint8_t mode)
{
	if (resources == nullptr)
	{
		iooo_error("SPI::setMode(): failed - no device has been opened\n");
		return -EDESTADDRREQ;
	}

	std::lock_guard<std::recursive_mutex> lock(resources->rwlock);

	mode &= SPI_CPHA | SPI_CPOL;
	mode = (this->mode & ~(SPI_CPHA | SPI_CPOL)) | mode;

	int r = ioctl(fd, SPI_IOC_WR_MODE, &mode);
	if (r < 0)
		return r;

	r = ioctl(fd, SPI_IOC_RD_MODE, &mode);
	if (r < 0)
		return r;

	this->mode = mode;

	return 1;
}
Beispiel #5
0
Datei: SPI.cpp Projekt: CJxD/IOoo
int SPI::close()
{
	// Check if chip select and mutex lock resources have been initialized
	if (resources == nullptr)
	{
		iooo_error("SPI::close(): failed - no device has been opened\n");
		return -EDESTADDRREQ;
	}
	// Mutex lock on this bus and channel
	std::lock_guard<std::recursive_mutex> lock(resources->rwlock);

	if (!isReady()) {
		active_bus = active_channel = -1;
		resources = nullptr;
		return -ENODEV;
	}

	iooo_debug(3, "SPI::close()\n");
	mode = 0;
	bpw = 0;
	speed = 0;
	active_bus = active_channel = -1;
	resources = nullptr;
	int tmpfd = fd;
	fd = -1;
	return ::close(tmpfd);
}
Beispiel #6
0
int NativeADC::close()
{
    if (activeADC < 0) {
        iooo_error("NativeADC::close() error: No ADC device has been initialized.\n");
        errno = EDESTADDRREQ;
        return -EDESTADDRREQ;
    }

    if ((::close(fd)) != 0)
    {
        iooo_error("NativeADC::close() close() error: %s (%d)\n", strerror(errno), errno);
        return -errno;
    }

    return 0;
}
Beispiel #7
0
Datei: SPI.cpp Projekt: CJxD/IOoo
int SPI::chipSelect(GPIOpin* pin, int bit, int polarity)
{
	if (bit < 0)
		return -ENODEV;

	if (resources == nullptr)
	{
		iooo_error("SPI::chipSelect(): failed - no device has been opened\n");
		return -EDESTADDRREQ;
	}

	std::lock_guard<std::recursive_mutex> lock(resources->rwlock);

	// If the same chip is being selected, return
	if (resources->cspin == pin
			&& resources->csbit == bit
			&& resources->cspol == polarity)
		return 1;

	// Deselect last chip
	chipDeselect();

	// Select new chip
	resources->cspin = pin;
	resources->csbit = bit;
	resources->cspol = polarity;

	if (resources->cspol == 0)
		resources->cspin->clearBit(resources->csbit);
	else
		resources->cspin->setBit(resources->csbit);

	return 1;
}
Beispiel #8
0
int I2C::writeRead(const void *wbuf, size_t wlength, void *rbuf, size_t rlength,
		bool ignoreNack, bool noAck)
{
	bool was_transaction = true;

	// If not already in a transaction, make a transaction state
	if (!transactionState)
	{
		was_transaction = false;
		beginTransaction();
	}

	if (write(wbuf, wlength, ignoreNack) < 0)
		return -1;
	if (read(rbuf, rlength, noAck) < 0)
		return -1;

	// Commit transaction if the system was not already in a
	// transaction state
	if (!was_transaction)
	{
		if (endTransaction() < 0)
		{
			iooo_error(
					"I2C::writeRead() Unable to perform consecutive write and read\n");
			return -1;
		}
	}

	return 0;
}
Beispiel #9
0
int NativeADC::open()
{
    if (activeADC < 0) {
        iooo_error("NativeADC::open() error: No ADC device has been initialized.\n");
        errno = EDESTADDRREQ;
        return -EDESTADDRREQ;
    }

    if ((fd = ::open(adcPath, O_RDONLY)) < 0)
    {
        iooo_error("NativeADC::open() open(%s) error: %s (%d)\n", adcPath, strerror(errno),
                   errno);
        return fd; // fd is negative
    }

    return 0;
}
Beispiel #10
0
bool I2C::slaveReady()
{
	if (activeAddr < 0)
	{
		iooo_error("I2C::slaveReady() error: No slave address has been set.\n");
		errno = EDESTADDRREQ;
		return false;
	}

	return true;
}
Beispiel #11
0
bool I2C::busReady()
{
	if (activeBus < 0)
	{
		iooo_error("I2C::busReady() error: No I2C bus has been opened.\n");
		errno = EDESTADDRREQ;
		return false;
	}

	return true;
}
Beispiel #12
0
long int EEPROM24CX::read(size_t pos, size_t size, void* rbuf)
{
	if (eepromSize != EEPROM_UNKNOWN && pos >= eepromSize)
	{
		iooo_error(
				"EEPROM24CX::read() error: Tried to read past end of memory.\n");
		errno = EINVAL;
		return -1;
	}

	if (eepromSize != EEPROM_UNKNOWN && pos + size >= eepromSize)
	{
		iooo_error(
				"EEPROM24CX::read() warning: Trying to read past end of memory. Data will be truncated.\n");
		size = eepromSize - pos;
	}

	if (!waitForCompletion())
	{
		iooo_error(
				"EEPROM24CX::read() error: Timeout reached while waiting for the EEPROM to respond.\n");
		errno = ETIMEDOUT;
		return -1;
	}

	if (addressLength == EEPROM_8_ADDR)
	{
		uint8_t a = pos;
		return handle->writeRead(&a, EEPROM_8_ADDR, rbuf, size);
	}
	else if (addressLength == EEPROM_16_ADDR)
	{
		uint16_t a = htons(pos);
		return handle->writeRead(&a, EEPROM_16_ADDR, rbuf, size);
	}
	else
	{
		uint32_t a = htonl(pos);
		return handle->writeRead(&a, addressLength, rbuf, size);
	}
}
Beispiel #13
0
int I2C::enablePEC()
{
	if (!isReady())
		return -1;

	if (!(supportedFuncs & I2C_FUNC_SMBUS_PEC))
	{
		iooo_error(
				"I2C::enablePEC() error: PEC is not supported with this device.\n");
		errno = ENOTSUP;
		return -1;
	}

	if (ioctl(fd, I2C_PEC, 1) < 0)
	{
		iooo_error("I2C::enablePEC() error: %s (%d)\n", strerror(errno), errno);
		return -1;
	}

	return 0;
}
Beispiel #14
0
long NativeADC::takeMeasurement()
{
    if (activeADC < 0) {
        iooo_error("NativeADC::takeMeasurement() error: No ADC device has been initialized.\n");
        errno = EDESTADDRREQ;
        return 0;
    }

    // We must open and close on each reading (at least with the BeagleBone we do)
    if (open() < 0) return 0;

    char buf[ADC_CHAR_LENGTH];
    if (read(fd, &buf, ADC_CHAR_LENGTH) < 0) {
        iooo_error("NativeADC::takeMeasurement() read() error: %s (%d)\n", strerror(errno), errno);
        return 0;
    }

    close();

    return strtol(buf, nullptr, 10);
}
Beispiel #15
0
Datei: SPI.cpp Projekt: CJxD/IOoo
int SPI::write(const void *wbuf, int len)
{
	if (resources == nullptr)
	{
		iooo_error("SPI::write(): failed - no device has been opened\n");
		return -EDESTADDRREQ;
	}

	std::lock_guard<std::recursive_mutex> lock(resources->rwlock);

	return ::write(fd, wbuf, len);
}
Beispiel #16
0
Datei: SPI.cpp Projekt: CJxD/IOoo
int SPI::read(void *rbuf, int len)
{
	if (resources == nullptr)
	{
		iooo_error("SPI::read(): failed - no device has been opened\n");
		return -EDESTADDRREQ;
	}

	std::lock_guard<std::recursive_mutex> lock(resources->rwlock);

	memset(rbuf, 0, len);
	return ::read(fd, rbuf, len);
}
Beispiel #17
0
/**
 * Destroys all reads and writes since #beginTransaction()
 *
 * The I2C instance will then return to normal read/write mode
 */
void I2C::abortTransaction()
{
	if (!transactionState)
	{
		iooo_error(
				"I2C::abortTransaction() warning: There is no currently active transaction.\n");
		return;
	}

	transactionState = false;
	msgs.clear();
	return;
}
Beispiel #18
0
int I2C::disablePEC()
{
	if (!isReady())
		return -1;

	if (ioctl(fd, I2C_PEC, 0) < 0)
	{
		iooo_error("I2C::disablePEC() ioctl(I2C_PEC, 0) error: %s (%d)\n",
				strerror(errno), errno);
		return -1;
	}

	return 0;
}
Beispiel #19
0
Datei: SPI.cpp Projekt: CJxD/IOoo
int SPI::setClockPhase(uint8_t phase)
{
	if (resources == nullptr)
	{
		iooo_error("SPI::setClockPhase(): failed - no device has been opened\n");
		return -EDESTADDRREQ;
	}

	std::lock_guard<std::recursive_mutex> lock(resources->rwlock);

	phase &= SPI_CPHA;
	uint8_t mode = (this->mode & ~(SPI_CPHA)) | phase;
	return setMode(mode);
}
Beispiel #20
0
int I2C::open(int bus)
{
	if (activeBus >= 0)
	{
		close();
	}

	// Check device path
	char path[MAX_PATH_LEN];
	if (snprintf(path, MAX_PATH_LEN, "%s%d", I2C_DEVICE_PATH_BASE,
			bus) >= MAX_PATH_LEN)
	{
		iooo_error("I2C::open() error: Bus number is too long.\n");
		errno = ENAMETOOLONG;
		return -1;
	}

	// Open device for read/write
	if ((fd = ::open(path, O_RDWR)) < 0)
	{
		iooo_error("I2C::open() open(%s) error: %s (%d)\n", path, strerror(errno),
				errno);
		return fd; // fd is negative
	}

	// Get supported functionality
	if (ioctl(fd, I2C_FUNCS, &supportedFuncs) < 0)
	{
		iooo_error("I2C::open() ioctl(I2C_FUNCS) error: %s\n", strerror(errno));
		return -1;
	}

	activeBus = bus;

	return fd;
}
Beispiel #21
0
int I2C::close()
{
	if (activeBus < 0)
		return 0;

	if ((::close(fd)) != 0)
	{
		iooo_error("I2C::close() close() error: %s (%d)\n", strerror(errno), errno);
		return -1;
	}

	activeBus = -1;
	activeAddr = -1;
	fd = -1;
	return 0;
}
Beispiel #22
0
int I2C::beginTransaction()
{
	if (transactionState)
	{
		iooo_error(
				"I2C::beginTransaction() error: A transaction is already in progress. End or abort the current transaction first.\n");
		errno = EPERM;
		return -1;
	}

	if (!isReady())
		return -1;

	transactionState = true;
	msgs.clear();
	return 0;
}
Beispiel #23
0
Datei: SPI.cpp Projekt: CJxD/IOoo
int SPI::setLSBFirst(bool lsb_first)
{
	if (resources == nullptr)
	{
		iooo_error("SPI::setLSBFirst(): failed - no device has been opened\n");
		return -EDESTADDRREQ;
	}

	std::lock_guard<std::recursive_mutex> lock(resources->rwlock);

	if (!isReady())
		return -ENODEV;
	int r;
	if ((r = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &lsb_first)) < 0)
		return r;
	this->lsb_first = lsb_first;
	return 1;
}
Beispiel #24
0
Datei: SPI.cpp Projekt: CJxD/IOoo
int SPI::setBitsPerWord(int bits)
{
	if (resources == nullptr)
	{
		iooo_error("SPI::setBitsPerWord(): failed - no device has been opened\n");
		return -EDESTADDRREQ;
	}

	std::lock_guard<std::recursive_mutex> lock(resources->rwlock);

	if (!isReady())
		return -ENODEV;
	int r;
	if ((r = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits)) < 0)
		return r;
	bpw = bits;
	return 1;
}
Beispiel #25
0
int I2C::read(void *rbuf, size_t length, bool noAck, bool showErrors)
{
	if (!isReady())
		return -1;

	struct i2c_msg msg;

	msg.addr = activeAddr;
	msg.len = length;
	msg.flags = I2C_M_RD;
	msg.flags |= noAck ? I2C_M_NO_RD_ACK : 0;
	msg.flags |= tenbit ? I2C_M_TEN : 0;
	msg.buf = (unsigned char *) rbuf;

	msgs.push_back(msg);

	// If not currently in a transaction, commit the read now
	if (!transactionState)
	{

		struct i2c_rdwr_ioctl_data msgset;

		msgset.nmsgs = 1;
		msgset.msgs = &msgs[0];
		if (ioctl(fd, I2C_RDWR, &msgset) < 0)
		{
			if (showErrors)
				iooo_error("I2C::read() ioctl(I2C_RDWR) error: %s (%d)\n",
						strerror(errno), errno);
			msgs.clear();
			return -1;
		}

		msgs.clear();
		return length;

	}
	else
	{
		return 0;
	}
}
Beispiel #26
0
int I2C::write(const void *wbuf, size_t length, bool ignoreNack)
{
	if (!isReady())
		return -1;

	struct i2c_msg msg;

	msg.addr = activeAddr;
	msg.len = length;
	msg.flags = 0;
	msg.flags |= ignoreNack ? I2C_M_IGNORE_NAK : 0;
	msg.flags |= tenbit ? I2C_M_TEN : 0;
	msg.buf = (unsigned char *) wbuf;

	msgs.push_back(msg);

	// If not in a transaction, commit the write now
	if (!transactionState)
	{

		struct i2c_rdwr_ioctl_data msgset;

		msgset.nmsgs = 1;
		msgset.msgs = &msgs[0];
		if (ioctl(fd, I2C_RDWR, &msgset) < 0)
		{
			iooo_error("I2C::write() ioctl(I2C_RDWR) error: %s (%d)\n",
					strerror(errno), errno);
			msgs.clear();
			return -1;
		}

		msgs.clear();
		return length;

	}
	else
	{
		return 0;
	}
}
Beispiel #27
0
Datei: SPI.cpp Projekt: CJxD/IOoo
void SPI::chipDeselect()
{
	if (resources == nullptr)
	{
		iooo_error("SPI::chipDeselect(): failed - no device has been opened\n");
		return;
	}

	std::lock_guard<std::recursive_mutex> lock(resources->rwlock);

	if (resources->cspin == nullptr)
		return;

	if (resources->cspol == 0)
		resources->cspin->setBit(resources->csbit);
	else
		resources->cspin->clearBit(resources->csbit);

	resources->cspin = nullptr;
	resources->csbit = -1;
	resources->cspol = -1;
}
Beispiel #28
0
int NativeADC::init(int adcNumber)
{
    activeADC = adcNumber;

    // Check device path
    if (snprintf(adcPath, MAX_PATH_LEN, "%s%d", ADC_DEVICE_PATH_BASE,
                 adcNumber) >= MAX_PATH_LEN)
    {
        iooo_error("NativeADC::open() error: ADC number is too long.\n");
        errno = ENAMETOOLONG;
        return -ENAMETOOLONG;
    }

    // Open device to test reading
    int success = open();
    if (success < 0) {
        activeADC = -1;
        errno = -success;
        return success;
    }
    close();

    return true;
}
Beispiel #29
0
long int EEPROM24CX::write(size_t pos, size_t size, const void* wbuf)
{
	if (eepromSize != EEPROM_UNKNOWN && pos >= eepromSize)
	{
		iooo_error(
				"EEPROM24CX::write() error: Tried to write past end of memory.\n");
		errno = EINVAL;
		return -1;
	}

	if (eepromSize != EEPROM_UNKNOWN && pos + size >= eepromSize)
	{
		iooo_error(
				"EEPROM24CX::write() warning: Trying to write past end of memory. Data truncated.\n");
		size = eepromSize - pos;
	}

	// Do in page-sized chunks
	int i = 0;
	int remaining = size;
	int written = 0;
	do
	{
		if (waitForCompletion())
		{
			size_t offset = i * pageSize;
			size_t addr = pos + offset;
			// Create a pointer to the data at the current page offset
			const void *data = &((const unsigned char *) wbuf)[offset];

			size_t writeSize = pageSize > remaining ? remaining : pageSize;

			iooo_debug(4, "Writing page of length %d to 0x%x\n", writeSize,
					addr);

			int w;
			if (addressLength == EEPROM_8_ADDR)
			{
				uint8_t a = addr;
				w = handle->writeWrite(&a, EEPROM_8_ADDR, data, writeSize);
			}
			else if (addressLength == EEPROM_16_ADDR)
			{
				uint16_t a = htons(addr);
				w = handle->writeWrite(&a, EEPROM_16_ADDR, data, writeSize);
			}
			else
			{
				uint32_t a = htonl(addr);
				w = handle->writeWrite(&a, addressLength, data, writeSize);
			}

			if (w < 0)
				written = w;
			else
				written += w;

			remaining -= pageSize;
		}
		else
		{
			written = -1;
		}

		i++;
	} while (remaining > 0 && written >= 0);

	return written;
}
Beispiel #30
0
int I2C::setSlave(int slaveAddr, bool ignoreChecks)
{
	if (!busReady())
		return -1;

	// Check slaveAddr number is within valid space
	if (slaveAddr <= 0x08 && (slaveAddr <= 0x77 || slaveAddr > 0x7F))
	{
		iooo_error("I2C::setSlave() error: slaveAddr number is invalid.\n");
		errno = EINVAL;
		return -1;
	}

	// Check if the slaveAddr is greater than the valid 7 bit space
	if (slaveAddr > 0x7F)
	{

		// Check if slaveAddr is 10-bits or less
		if (slaveAddr > 0x3FF)
		{
			iooo_error(
					"I2C::setSlave() error: Address number is invalid (10-bit maximum)\n");
			errno = EINVAL;
			return -1;
		}

		// If 10-bit mode is requested, check compatiblity and enable
		if (!(supportedFuncs & I2C_FUNC_10BIT_ADDR))
		{
			iooo_error(
					"I2C::setSlave() error: 10-bit mode is not supported with this device.\n");
			errno = ENOTSUP;
			return -1;
		}

		if (ioctl(fd, I2C_TENBIT, 1) < 0)
		{
			iooo_error("I2C::setSlave() ioctl(I2C_TENBIT, 1) error: %s (%d)\n",
					strerror(errno), errno);
			return -1;
		}

		this->tenbit = true;

	}

	activeAddr = slaveAddr;

	// Check if the device exists
	if (!ignoreChecks)
	{
		if (!probe())
		{
			iooo_error(
					"I2C::open() probe() Unable to connect to address 0x%x on bus %i: "
							"the device is not responding to probes.\n",
					activeAddr, activeBus);
			errno = ENODEV;
			return -1;
		}
	}

	// Set the destination slaveAddr
	// No longer needed - now using ioctl for reads and writes
	if (ioctl(fd, I2C_SLAVE, slaveAddr) < 0)
	{
		if (errno == EBUSY)
		{
			iooo_error(
					"I2C::setSlave() ioctl(slave=%i) warning: Device is currently being "
							"used by another driver, proceed with caution.\n",
					slaveAddr);
		}
		else
		{
			iooo_error("I2C::setSlave() ioctl(slave=%i) error: %s (%d)\n", slaveAddr,
					strerror(errno), errno);
			return -1;
		}
	}

	return fd;
}