|
/**
|
|
* \file spidevice.cpp
|
|
*
|
|
* \brief Wrapper class to communicate to device via spidev
|
|
*
|
|
* Websites:
|
|
* Critical Link - http://www.criticallink.com
|
|
*
|
|
* \copyright Critical Link LLC 2015
|
|
*/
|
|
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
|
|
#include "spidevice.h"
|
|
|
|
tcSPIDevice::tcSPIDevice(std::string asDevice)
|
|
:msDevice(asDevice), mnFileDescriptor(-1)
|
|
{
|
|
openDevice();
|
|
}
|
|
|
|
tcSPIDevice::tcSPIDevice(const char* asDevice)
|
|
:msDevice(asDevice), mnFileDescriptor(-1)
|
|
{
|
|
openDevice();
|
|
}
|
|
|
|
tcSPIDevice::~tcSPIDevice()
|
|
{
|
|
closeDevice();
|
|
}
|
|
|
|
void tcSPIDevice::openDevice()
|
|
{
|
|
if(!this->isOpen()) {
|
|
mnFileDescriptor = open(msDevice.c_str(), O_RDWR);
|
|
|
|
if (mnFileDescriptor < 0) {
|
|
perror("SPIDevice constructor");
|
|
}
|
|
}
|
|
}
|
|
|
|
void tcSPIDevice::closeDevice()
|
|
{
|
|
if (mnFileDescriptor >= 0) {
|
|
close(mnFileDescriptor);
|
|
mnFileDescriptor = -1;
|
|
}
|
|
}
|
|
|
|
bool tcSPIDevice::isOpen()
|
|
{
|
|
return !(mnFileDescriptor < 0);
|
|
}
|
|
|
|
tsSPIConfiguration tcSPIDevice::getConfiguration()
|
|
{
|
|
tsSPIConfiguration rv;
|
|
|
|
rv.mnMode = -1;
|
|
rv.mnBits = -1;
|
|
rv.mnLsbType = -1;
|
|
rv.mnSpeed = -1;
|
|
|
|
if (ioctl(mnFileDescriptor, SPI_IOC_RD_MODE, &(rv.mnMode)) < 0) {
|
|
perror("SPI rd_mode");
|
|
}
|
|
|
|
if (ioctl(mnFileDescriptor, SPI_IOC_RD_LSB_FIRST, &(rv.mnLsbType))
|
|
< 0) {
|
|
perror("SPI rd_lsb_fist");
|
|
}
|
|
|
|
if (ioctl(mnFileDescriptor, SPI_IOC_RD_BITS_PER_WORD, &(rv.mnBits))
|
|
< 0) {
|
|
perror("SPI rd_bits_per_word");
|
|
}
|
|
|
|
if (ioctl(mnFileDescriptor, SPI_IOC_RD_MAX_SPEED_HZ, &(rv.mnSpeed))
|
|
< 0) {
|
|
perror("SPI rd_max_speed_hz");
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
bool tcSPIDevice::setConfiguration(struct tsSPIConfiguration &arConfiguration)
|
|
{
|
|
bool rv = true;
|
|
|
|
if (ioctl(mnFileDescriptor, SPI_IOC_WR_MODE, &(arConfiguration.mnMode))
|
|
< 0) {
|
|
perror("SPI wr_mode");
|
|
rv = false;
|
|
}
|
|
|
|
if (ioctl(mnFileDescriptor, SPI_IOC_WR_LSB_FIRST,
|
|
&(arConfiguration.mnLsbType)) < 0) {
|
|
perror("SPI wr_lsb_fist");
|
|
rv = false;
|
|
}
|
|
|
|
if (ioctl(mnFileDescriptor, SPI_IOC_WR_BITS_PER_WORD,
|
|
&(arConfiguration.mnBits)) < 0) {
|
|
perror("SPI wr_bits_per_word");
|
|
rv = false;
|
|
}
|
|
|
|
if (ioctl(mnFileDescriptor, SPI_IOC_WR_MAX_SPEED_HZ,
|
|
&(arConfiguration.mnSpeed)) < 0) {
|
|
perror("SPI wr_max_speed_hz");
|
|
rv = false;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
void tcSPIDevice::write(char *apTxData, long anLen)
|
|
{
|
|
::write(mnFileDescriptor, apTxData, anLen);
|
|
}
|
|
|
|
void tcSPIDevice::read(char *apRxData, long anLen)
|
|
{
|
|
::read(mnFileDescriptor, apRxData, anLen);
|
|
}
|
|
|
|
void tcSPIDevice::duplex(char *apTxData, char *apRxData, long anLen)
|
|
{
|
|
struct spi_ioc_transfer xfer;
|
|
int status;
|
|
|
|
/* clear out the transfer struct */
|
|
memset(&xfer, 0, sizeof(xfer));
|
|
|
|
/* set the data to transfer; this is a pointer */
|
|
xfer.tx_buf = (unsigned long) apTxData;
|
|
/* set the length of the data to transfer in bytes */
|
|
xfer.len = anLen;
|
|
|
|
/* set the buffer for the data to receive; this can be NULL */
|
|
xfer.rx_buf = (unsigned long) apRxData;
|
|
/* length is in bytes */
|
|
xfer.len = anLen;
|
|
|
|
/* perform the operation, SPI_IOC_MESSAGE is 1 because there is only 1 frame message occurring */
|
|
status = ioctl(mnFileDescriptor, SPI_IOC_MESSAGE(1), &xfer);
|
|
if (status < 0) {
|
|
perror("SPI_IOC_MESSAGE");
|
|
}
|
|
}
|