Project

General

Profile

RE: We want to know about SPI for CAN Interface with Linux » spidevice.cpp

Jonathan Cormier, 02/28/2019 04:44 PM

 
/**
* \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");
}
}
(1-1/2)