SystemAgent/src/drivers/user_spi_driver.c

92 lines
2.3 KiB
C

#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/spi/spidev.h>
#include <linux/types.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "drivers/user_config_driver.h"
#include "utils/user_log_util.h"
#include "drivers/user_spi_driver.h"
int user_spi_driver_init(user_spi_driver_t *spi, char *path,
uint32_t speed_hz) {
USER_LOG(USER_LOG_INFO, "SPI driver init.");
spi->spidev_fd = open(path, O_RDWR);
if(spi->spidev_fd < 0) {
USER_LOG(USER_LOG_ERROR, "Failed to open spidev device, %s",
strerror(errno));
return -1;
}
spi->speed_hz = speed_hz;
uint32_t mode = SPI_MODE_0;
if(ioctl(spi->spidev_fd, SPI_IOC_WR_MODE32, &mode) == -1) {
USER_LOG(USER_LOG_ERROR, "Failed to set SPI mode.");
return -1;
}
uint32_t bits = 8;
if(ioctl(spi->spidev_fd, SPI_IOC_WR_BITS_PER_WORD, &bits) == -1) {
USER_LOG(USER_LOG_ERROR, "Failed to set SPI bits per word.");
return -1;
}
return 0;
}
int user_spi_driver_deinit(user_spi_driver_t *spi) {
USER_LOG(USER_LOG_INFO, "SPI driver deinit.");
close(spi->spidev_fd);
return 0;
}
int user_spi_driver_xfer(user_spi_driver_t *spi, uint8_t *tx_buf,
uint8_t *rx_buf, uint32_t len) {
struct spi_ioc_transfer txn = {
.tx_buf = (unsigned long)tx_buf,
.rx_buf = (unsigned long)rx_buf,
.len = len,
.cs_change = 0,
.speed_hz = spi->speed_hz,
.bits_per_word = 8,
.tx_nbits = 1,
.rx_nbits = 1,
};
USER_LOG(USER_LOG_DEBUG, "SPI 1st byte: 0x%02x.", tx_buf[0]);
while(len > SPIDEV_MAX_TRANSFER_SIZE) {
txn.len = SPIDEV_MAX_TRANSFER_SIZE;
len -= SPIDEV_MAX_TRANSFER_SIZE;
USER_LOG(USER_LOG_DEBUG, "SPI Tx len: %d.", txn.len);
if(ioctl(spi->spidev_fd, SPI_IOC_MESSAGE(1), &txn) < 0) {
USER_LOG(USER_LOG_ERROR, "SPI transaction error.");
return -1;
}
}
if(len > 0) {
txn.len = len;
USER_LOG(USER_LOG_DEBUG, "SPI Tx len: %d.", txn.len);
if(ioctl(spi->spidev_fd, SPI_IOC_MESSAGE(1), &txn) < 0) {
USER_LOG(USER_LOG_ERROR, "SPI transaction error.");
return -1;
}
}
return 0;
}