summaryrefslogtreecommitdiff
path: root/loragw_hal/src/loragw_spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'loragw_hal/src/loragw_spi.c')
-rw-r--r--loragw_hal/src/loragw_spi.c237
1 files changed, 145 insertions, 92 deletions
diff --git a/loragw_hal/src/loragw_spi.c b/loragw_hal/src/loragw_spi.c
index fa8581c..d6e3eb0 100644
--- a/loragw_hal/src/loragw_spi.c
+++ b/loragw_hal/src/loragw_spi.c
@@ -20,6 +20,7 @@ Description:
#include <stdint.h> /* C99 types */
#include <stdio.h> /* printf fprintf */
+#include <stdlib.h> /* malloc free */
#include <unistd.h> /* lseek, close */
#include <fcntl.h> /* open */
#include <string.h> /* memset */
@@ -55,70 +56,95 @@ Description:
/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */
/* SPI initialization and configuration */
-int lgw_spi_open(int *spi_device) {
- int i,j,k,l;
+int lgw_spi_open(void **spi_target_ptr) {
+ int *spi_device = NULL;
+ int dev;
+ int a,b,c;
+ int i;
- CHECK_NULL(spi_device);
+ /* check input variables */
+ CHECK_NULL(spi_target_ptr); /* cannot be null, must point on a void pointer (*spi_target_ptr can be null) */
+
+ /* allocate memory for the device descriptor */
+ spi_device = malloc(sizeof(int));
+ if (spi_device == NULL) {
+ DEBUG_MSG("ERROR: MALLOC FAIL\n");
+ return LGW_SPI_ERROR;
+ }
/* open SPI device */
- i = open(SPI_DEV_PATH, O_RDWR);
- if (i < 0) {
+ dev = open(SPI_DEV_PATH, O_RDWR);
+ if (dev < 0) {
DEBUG_MSG("SPI port fail to open\n");
return LGW_SPI_ERROR;
}
/* setting SPI mode to 'mode 0' */
- j = SPI_MODE_0;
- k = ioctl(i, SPI_IOC_WR_MODE, &j);
- l = ioctl(i, SPI_IOC_RD_MODE, &j);
- if ((k < 0) || (l < 0)) {
+ i = SPI_MODE_0;
+ a = ioctl(dev, SPI_IOC_WR_MODE, &i);
+ b = ioctl(dev, SPI_IOC_RD_MODE, &i);
+ if ((a < 0) || (b < 0)) {
DEBUG_MSG("ERROR: SPI PORT FAIL TO SET IN MODE 0\n");
- close(i);
+ close(dev);
+ free(spi_device);
return LGW_SPI_ERROR;
}
/* setting SPI max clk (in Hz) */
- j = SPI_SPEED;
- k = ioctl(i, SPI_IOC_WR_MAX_SPEED_HZ, &j);
- l = ioctl(i, SPI_IOC_RD_MAX_SPEED_HZ, &j);
- if ((k < 0) || (l < 0)) {
+ i = SPI_SPEED;
+ a = ioctl(dev, SPI_IOC_WR_MAX_SPEED_HZ, &i);
+ b = ioctl(dev, SPI_IOC_RD_MAX_SPEED_HZ, &i);
+ if ((a < 0) || (b < 0)) {
DEBUG_MSG("ERROR: SPI PORT FAIL TO SET MAX SPEED\n");
- close(i);
+ close(dev);
+ free(spi_device);
return LGW_SPI_ERROR;
}
/* setting SPI to MSB first */
- j = 0;
- k = ioctl(i, SPI_IOC_WR_LSB_FIRST, &j);
- l = ioctl(i, SPI_IOC_RD_LSB_FIRST, &j);
- if ((k < 0) || (l < 0)) {
+ i = 0;
+ a = ioctl(dev, SPI_IOC_WR_LSB_FIRST, &i);
+ b = ioctl(dev, SPI_IOC_RD_LSB_FIRST, &i);
+ if ((a < 0) || (b < 0)) {
DEBUG_MSG("ERROR: SPI PORT FAIL TO SET MSB FIRST\n");
- close(i);
+ close(dev);
+ free(spi_device);
return LGW_SPI_ERROR;
}
/* setting SPI to 8 bits per word */
- j = 0;
- k = ioctl(i, SPI_IOC_WR_BITS_PER_WORD, &j);
- l = ioctl(i, SPI_IOC_RD_BITS_PER_WORD, &j);
- if ((k < 0) || (l < 0)) {
+ i = 0;
+ a = ioctl(dev, SPI_IOC_WR_BITS_PER_WORD, &i);
+ b = ioctl(dev, SPI_IOC_RD_BITS_PER_WORD, &i);
+ if ((a < 0) || (b < 0)) {
DEBUG_MSG("ERROR: SPI PORT FAIL TO SET 8 BITS-PER-WORD\n");
- close(i);
+ close(dev);
return LGW_SPI_ERROR;
}
- DEBUG_MSG("Note: SPI port opened and configured ok\n");
- *spi_device = i;
+
+ *spi_device = dev;
+ *spi_target_ptr = (void *)spi_device;
+ DEBUG_MSG("Note: SPI port opened and configured ok\n");
return LGW_SPI_SUCCESS;
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* SPI release */
-int lgw_spi_close(int spi_device) {
- int i;
+int lgw_spi_close(void *spi_target) {
+ int spi_device;
+ int a;
+
+ /* check input variables */
+ CHECK_NULL(spi_target);
+
+ /* close file & deallocate file descriptor */
+ spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */
+ a = close(spi_device);
+ free(spi_target);
- i = close(spi_device);
- if (i < 0) {
+ /* determine return code */
+ if (a < 0) {
DEBUG_MSG("ERROR: SPI PORT FAILED TO CLOSE\n");
return LGW_SPI_ERROR;
} else {
@@ -130,24 +156,35 @@ int lgw_spi_close(int spi_device) {
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* Simple write */
-int lgw_spi_w(int spi_device, uint8_t address, uint8_t data) {
- uint8_t outbuf[2];
+int lgw_spi_w(void *spi_target, uint8_t address, uint8_t data) {
+ int spi_device;
+ uint8_t out_buf[2];
struct spi_ioc_transfer k;
- int i;
+ int a;
- outbuf[0] = WRITE_ACCESS | (address & 0x7F);
- outbuf[1] = data;
+ /* check input variables */
+ CHECK_NULL(spi_target);
+ if ((address & 0x80) != 0) {
+ DEBUG_MSG("WARNING: SPI address > 127\n");
+ }
+ spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */
+
+ /* prepare frame to be sent */
+ out_buf[0] = WRITE_ACCESS | (address & 0x7F);
+ out_buf[1] = data;
+
+ /* I/O transaction */
memset(&k, 0, sizeof(k)); /* clear k */
- k.tx_buf = (unsigned long) outbuf;
- k.len = ARRAY_SIZE(outbuf);
+ k.tx_buf = (unsigned long) out_buf;
+ k.len = ARRAY_SIZE(out_buf);
k.speed_hz = SPI_SPEED;
k.cs_change = 1;
k.bits_per_word = 8;
+ a = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k);
- i = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k);
-
- if (i != 2) {
+ /* determine return code */
+ if (a != 2) {
DEBUG_MSG("ERROR: SPI WRITE FAILURE\n");
return LGW_SPI_ERROR;
} else {
@@ -159,31 +196,41 @@ int lgw_spi_w(int spi_device, uint8_t address, uint8_t data) {
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* Simple read */
-int lgw_spi_r(int spi_device, uint8_t address, uint8_t *data) {
- uint8_t outbuf[2];
- uint8_t inbuf[ARRAY_SIZE(outbuf)];
+int lgw_spi_r(void *spi_target, uint8_t address, uint8_t *data) {
+ int spi_device;
+ uint8_t out_buf[2];
+ uint8_t in_buf[ARRAY_SIZE(out_buf)];
struct spi_ioc_transfer k;
- int i;
+ int a;
+ /* check input variables */
+ CHECK_NULL(spi_target);
+ if ((address & 0x80) != 0) {
+ DEBUG_MSG("WARNING: SPI address > 127\n");
+ }
CHECK_NULL(data);
- outbuf[0] = READ_ACCESS | (address & 0x7F);
- outbuf[1] = 0x00;
+ spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */
+ /* prepare frame to be sent */
+ out_buf[0] = READ_ACCESS | (address & 0x7F);
+ out_buf[1] = 0x00;
+
+ /* I/O transaction */
memset(&k, 0, sizeof(k)); /* clear k */
- k.tx_buf = (unsigned long) outbuf;
- k.rx_buf = (unsigned long) inbuf;
- k.len = ARRAY_SIZE(outbuf);
+ k.tx_buf = (unsigned long) out_buf;
+ k.rx_buf = (unsigned long) in_buf;
+ k.len = ARRAY_SIZE(out_buf);
k.cs_change = 1;
+ a = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k);
- i = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k);
-
- if (i != 2) {
+ /* determine return code */
+ if (a != 2) {
DEBUG_MSG("ERROR: SPI READ FAILURE\n");
return LGW_SPI_ERROR;
} else {
DEBUG_MSG("Note: SPI read success\n");
- *data = inbuf[1];
+ *data = in_buf[1];
return LGW_SPI_SUCCESS;
}
}
@@ -191,45 +238,48 @@ int lgw_spi_r(int spi_device, uint8_t address, uint8_t *data) {
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* Burst (multiple-byte) write */
-int lgw_spi_wb(int spi_device, uint8_t address, uint8_t *data, uint16_t size) {
+int lgw_spi_wb(void *spi_target, uint8_t address, uint8_t *data, uint16_t size) {
+ int spi_device;
uint8_t command;
struct spi_ioc_transfer k[2];
- int byte_to_trans;
- int chunk_size;
- int offset = 0;
+ int size_to_do, chunk_size, offset;
int byte_transfered = 0;
+ int i;
/* check input parameters */
+ CHECK_NULL(spi_target);
+ if ((address & 0x80) != 0) {
+ DEBUG_MSG("WARNING: SPI address > 127\n");
+ }
CHECK_NULL(data);
if (size == 0) {
DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n");
return LGW_SPI_ERROR;
}
- if (address > 0x7F) {
- DEBUG_MSG("ERROR: ADDRESS OUT OF SPI RANGE\n");
- return LGW_SPI_ERROR;
- }
- memset(&k, 0, sizeof(k)); /* clear k */
+ spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */
+
+ /* prepare command byte */
command = WRITE_ACCESS | (address & 0x7F);
+ size_to_do = size;
+
+ /* I/O transaction */
+ memset(&k, 0, sizeof(k)); /* clear k */
k[0].tx_buf = (unsigned long) &command;
k[0].len = 1;
k[0].cs_change = 0;
k[1].cs_change = 1;
-
- byte_to_trans = size;
- while (byte_to_trans > 0) {
- chunk_size = (byte_to_trans < LGW_BURST_CHUNK) ? byte_to_trans : LGW_BURST_CHUNK;
+ for (i=0; size_to_do > 0; ++i) {
+ chunk_size = (size_to_do < LGW_BURST_CHUNK) ? size_to_do : LGW_BURST_CHUNK;
+ offset = i * LGW_BURST_CHUNK;
k[1].tx_buf = (unsigned long)(data + offset);
k[1].len = chunk_size;
-
byte_transfered += (ioctl(spi_device, SPI_IOC_MESSAGE(2), &k) - 1 );
- DEBUG_PRINTF("BURST WRITE: to trans %d # chunk %d # transferred %d \n", byte_to_trans, chunk_size, byte_transfered);
-
- byte_to_trans -= chunk_size;
- offset += chunk_size;
- }
+ DEBUG_PRINTF("BURST WRITE: to trans %d # chunk %d # transferred %d \n", size_to_do, chunk_size, byte_transfered);
+ size_to_do -= chunk_size; /* subtract the quantity of data already transferred */
+ }
+ /* determine return code */
if (byte_transfered != size) {
DEBUG_MSG("ERROR: SPI BURST WRITE FAILURE\n");
return LGW_SPI_ERROR;
@@ -242,45 +292,48 @@ int lgw_spi_wb(int spi_device, uint8_t address, uint8_t *data, uint16_t size) {
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* Burst (multiple-byte) read */
-int lgw_spi_rb(int spi_device, uint8_t address, uint8_t *data, uint16_t size) {
+int lgw_spi_rb(void *spi_target, uint8_t address, uint8_t *data, uint16_t size) {
+ int spi_device;
uint8_t command;
struct spi_ioc_transfer k[2];
- int byte_to_trans;
- int chunk_size;
- int offset = 0;
+ int size_to_do, chunk_size, offset;
int byte_transfered = 0;
+ int i;
/* check input parameters */
+ CHECK_NULL(spi_target);
+ if ((address & 0x80) != 0) {
+ DEBUG_MSG("WARNING: SPI address > 127\n");
+ }
CHECK_NULL(data);
if (size == 0) {
DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n");
return LGW_SPI_ERROR;
}
- if (address > 0x7F) {
- DEBUG_MSG("ERROR: ADDRESS OUT OF SPI RANGE\n");
- return LGW_SPI_ERROR;
- }
- memset(&k, 0, sizeof(k)); /* clear k */
+ spi_device = *(int *)spi_target; /* must check that spi_target is not null beforehand */
+
+ /* prepare command byte */
command = READ_ACCESS | (address & 0x7F);
+ size_to_do = size;
+
+ /* I/O transaction */
+ memset(&k, 0, sizeof(k)); /* clear k */
k[0].tx_buf = (unsigned long) &command;
k[0].len = 1;
k[0].cs_change = 0;
k[1].cs_change = 1;
-
- byte_to_trans = size;
- while (byte_to_trans > 0) {
- chunk_size = (byte_to_trans < LGW_BURST_CHUNK) ? byte_to_trans : LGW_BURST_CHUNK;
+ for (i=0; size_to_do > 0; ++i) {
+ chunk_size = (size_to_do < LGW_BURST_CHUNK) ? size_to_do : LGW_BURST_CHUNK;
+ offset = i * LGW_BURST_CHUNK;
k[1].rx_buf = (unsigned long)(data + offset);
k[1].len = chunk_size;
-
byte_transfered += (ioctl(spi_device, SPI_IOC_MESSAGE(2), &k) - 1 );
- DEBUG_PRINTF("BURST READ: to trans %d # chunk %d # transferred %d \n", byte_to_trans, chunk_size, byte_transfered);
-
- byte_to_trans -= chunk_size;
- offset += chunk_size;
- }
+ DEBUG_PRINTF("BURST READ: to trans %d # chunk %d # transferred %d \n", size_to_do, chunk_size, byte_transfered);
+ size_to_do -= chunk_size; /* subtract the quantity of data already transferred */
+ }
+ /* determine return code */
if (byte_transfered != size) {
DEBUG_MSG("ERROR: SPI BURST READ FAILURE\n");
return LGW_SPI_ERROR;