File 0001-Added-USB-support-via-ftdi.patch of Package basicstation
From 04be5f46bda42cee0e2e1fccb4ae4bc2a0469ca3 Mon Sep 17 00:00:00 2001
From: Frank Kunz <mailinglists@kunz-im-inter.net>
Date: Mon, 10 Aug 2020 20:09:18 +0200
Subject: [PATCH] Added USB support via ftdi
Signed-off-by: Frank Kunz <mailinglists@kunz-im-inter.net>
---
libloragw/Makefile | 28 ++-
libloragw/library.cfg | 9 +
libloragw/src/loragw_spi.ftdi.c | 299 ++++++++++++++++++++++++++++++++
util_lbt_test/Makefile | 2 +-
util_pkt_logger/Makefile | 2 +-
util_spectral_scan/Makefile | 2 +-
util_spi_stress/Makefile | 2 +-
util_tx_continuous/Makefile | 2 +-
util_tx_test/Makefile | 2 +-
9 files changed, 339 insertions(+), 9 deletions(-)
create mode 100644 libloragw/src/loragw_spi.ftdi.c
diff --git a/libloragw/Makefile b/libloragw/Makefile
index 53c33d9..567a099 100644
--- a/libloragw/Makefile
+++ b/libloragw/Makefile
@@ -14,10 +14,25 @@ CFLAGS := -O2 -Wall -Wextra -std=c99 -Iinc -I.
OBJDIR = obj
INCLUDES = $(wildcard inc/*.h)
+### library.cfg configuration file processing
+
+ifeq ($(CFG_SPI),native)
+ CFG_SPI_MSG := Linux native SPI driver
+ CFG_SPI_OPT := CFG_SPI_NATIVE
+else ifeq ($(CFG_SPI),ftdi)
+ CFG_SPI_MSG := FTDI SPI-over-USB bridge using libmpsse/libftdi/libusb
+ CFG_SPI_OPT := CFG_SPI_FTDI
+else
+ $(error No SPI physical layer selected, check ../target.cfg file.)
+endif
### linking options
-LIBS := -lloragw -lrt -lm
+ifeq ($(CFG_SPI),native)
+ LIBS := -lloragw -lrt -lm
+else ifeq ($(CFG_SPI),ftdi)
+ LIBS := -lloragw -lrt -lmpsse -lm
+endif
### general build targets
@@ -40,7 +55,10 @@ inc/config.h: ../VERSION library.cfg
# Release version
@echo "Release version : $(LIBLORAGW_VERSION)"
@echo " #define LIBLORAGW_VERSION "\"$(LIBLORAGW_VERSION)\""" >> $@
- # Debug options
+ # SPI interface
+ @echo "SPI interface : $(CFG_SPI_MSG)"
+ @echo " #define $(CFG_SPI_OPT) 1" >> $@
+ # Debug options
@echo " #define DEBUG_AUX $(DEBUG_AUX)" >> $@
@echo " #define DEBUG_SPI $(DEBUG_SPI)" >> $@
@echo " #define DEBUG_REG $(DEBUG_REG)" >> $@
@@ -60,9 +78,13 @@ $(OBJDIR):
$(OBJDIR)/%.o: src/%.c $(INCLUDES) inc/config.h | $(OBJDIR)
$(CC) -c $(CFLAGS) $< -o $@
+ifeq ($(CFG_SPI),native)
$(OBJDIR)/loragw_spi.o: src/loragw_spi.native.c $(INCLUDES) inc/config.h | $(OBJDIR)
$(CC) -c $(CFLAGS) $< -o $@
-
+else ifeq ($(CFG_SPI),ftdi)
+$(OBJDIR)/loragw_spi.o: src/loragw_spi.ftdi.c $(INCLUDES) inc/config.h | $(OBJDIR)
+ $(CC) -c $(CFLAGS) $< -o $@
+endif
$(OBJDIR)/loragw_hal.o: src/loragw_hal.c $(INCLUDES) src/arb_fw.var src/agc_fw.var src/cal_fw.var inc/config.h | $(OBJDIR)
$(CC) -c $(CFLAGS) $< -o $@
diff --git a/libloragw/library.cfg b/libloragw/library.cfg
index f962ba2..f627325 100644
--- a/libloragw/library.cfg
+++ b/libloragw/library.cfg
@@ -1,5 +1,14 @@
# That file will be included in the Makefile files that have hardware dependencies
+### SPI interface to the concentrator ###
+# Accepted values:
+# native Linux native SPI driver (RECOMMENDED).
+# Note: check the value of /dev/spidevX.X defined in source code
+# to ensure the right device will be opened on your platform.
+# ftdi FTDI SPI-over-USB bridge using libmpsse/libftdi/libusb
+
+CFG_SPI= ftdi
+
### Debug options ###
# Set the DEBUG_* to 1 to activate debug mode in individual modules.
# Warning: that makes the module *very verbose*, do not use for production
diff --git a/libloragw/src/loragw_spi.ftdi.c b/libloragw/src/loragw_spi.ftdi.c
new file mode 100644
index 0000000..15820ed
--- /dev/null
+++ b/libloragw/src/loragw_spi.ftdi.c
@@ -0,0 +1,299 @@
+/*
+ / _____) _ | |
+( (____ _____ ____ _| |_ _____ ____| |__
+ \____ \| ___ | (_ _) ___ |/ ___) _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+ (C)2013 Semtech-Cycleo
+
+Description:
+ Host specific functions to address the LoRa concentrator registers through
+ a SPI interface.
+ Single-byte read/write and burst read/write.
+ Does not handle pagination.
+ Could be used with multiple SPI ports in parallel (explicit file descriptor)
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+Maintainer: Sylvain Miermont
+*/
+
+
+/* -------------------------------------------------------------------------- */
+/* --- DEPENDANCIES --------------------------------------------------------- */
+
+#include <stdint.h> /* C99 types */
+#include <stdio.h> /* printf fprintf */
+#include <stdlib.h> /* malloc free */
+#include <string.h> /* memcpy */
+
+#define LIBFTDI1 1
+#include <mpsse.h>
+
+#include "loragw_spi.h"
+
+/* -------------------------------------------------------------------------- */
+/* --- PRIVATE MACROS ------------------------------------------------------- */
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#if DEBUG_SPI == 1
+ #define DEBUG_MSG(str) fprintf(stderr, str)
+ #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args)
+ #define CHECK_NULL(a) if(a==NULL){fprintf(stderr,"%s:%d: ERROR: NULL POINTER AS ARGUMENT\n", __FUNCTION__, __LINE__);return LGW_SPI_ERROR;}
+#else
+ #define DEBUG_MSG(str)
+ #define DEBUG_PRINTF(fmt, args...)
+ #define CHECK_NULL(a) if(a==NULL){return LGW_SPI_ERROR;}
+#endif
+
+/* -------------------------------------------------------------------------- */
+/* --- PRIVATE CONSTANTS ---------------------------------------------------- */
+
+#define READ_ACCESS 0x00
+#define WRITE_ACCESS 0x80
+
+/* parameters for a FT2232H */
+#define VID 0x0403
+#define PID 0x6010
+
+/* -------------------------------------------------------------------------- */
+/* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */
+
+/* SPI initialization and configuration */
+int lgw_spi_open(void **spi_target_ptr) {
+ struct mpsse_context *mpsse = NULL;
+ int a, b;
+
+ /* check input variables */
+ CHECK_NULL(spi_target_ptr); /* cannot be null, must point on a void pointer (*spi_target_ptr can be null) */
+
+ /* try to open the first available FTDI device matching VID/PID parameters */
+ mpsse = OpenIndex(VID,PID,SPI0, SIX_MHZ, MSB, IFACE_A, NULL, NULL, 0);
+ if (mpsse == NULL) {
+ DEBUG_MSG("ERROR: MPSSE OPEN FUNCTION RETURNED NULL\n");
+ return LGW_SPI_ERROR;
+ }
+ if (mpsse->open != 1) {
+ DEBUG_MSG("ERROR: MPSSE OPEN FUNCTION FAILED\n");
+ return LGW_SPI_ERROR;
+ }
+
+ /* toggle pin ADBUS5 of the FT2232H */
+ /* On the Semtech reference board, it resets the SX1301 */
+ a = PinHigh(mpsse, GPIOL1);
+ b = PinLow(mpsse, GPIOL1);
+ if ((a != MPSSE_OK) || (b != MPSSE_OK)) {
+ DEBUG_MSG("ERROR: IMPOSSIBLE TO TOGGLE GPIOL1/ADBUS5\n");
+ return LGW_SPI_ERROR;
+ }
+
+ DEBUG_PRINTF("SPI port opened and configured ok\ndesc: %s\nPID: 0x%04X\nVID: 0x%04X\nclock: %d\nLibmpsse version: 0x%02X\n", GetDescription(mpsse), GetPid(mpsse), GetVid(mpsse), GetClock(mpsse), Version());
+ *spi_target_ptr = (void *)mpsse;
+ return LGW_SPI_SUCCESS;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+/* SPI release */
+int lgw_spi_close(void *spi_target) {
+ struct mpsse_context *mpsse = spi_target;
+
+ /* check input variables */
+ CHECK_NULL(spi_target);
+
+ Close(mpsse);
+
+ /* close return no status, assume success (0_o) */
+ return LGW_SPI_SUCCESS;
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+/* Simple write */
+/* transaction time: .6 to 1 ms typically */
+int lgw_spi_w(void *spi_target,uint8_t spi_mux_mode, uint8_t spi_mux_target, uint8_t address, uint8_t data) {
+ struct mpsse_context *mpsse = spi_target;
+ uint8_t out_buf[2];
+ int a, b, c;
+
+ /* check input variables */
+ CHECK_NULL(spi_target);
+ if ((address & 0x80) != 0) {
+ DEBUG_MSG("WARNING: SPI address > 127\n");
+ }
+
+ /* prepare frame to be sent */
+ out_buf[0] = WRITE_ACCESS | (address & 0x7F);
+ out_buf[1] = data;
+
+ /* MPSSE transaction */
+ a = Start(mpsse);
+ b = FastWrite(mpsse, (char *)out_buf, 2);
+ c = Stop(mpsse);
+
+ /* determine return code */
+ if ((a != MPSSE_OK) || (b != MPSSE_OK) || (c != MPSSE_OK)) {
+ DEBUG_MSG("ERROR: SPI WRITE FAILURE\n");
+ return LGW_SPI_ERROR;
+ } else {
+ DEBUG_MSG("Note: SPI write success\n");
+ return LGW_SPI_SUCCESS;
+ }
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+/* Simple read (using Transfer function) */
+/* transaction time: 1.1 to 2 ms typically */
+int lgw_spi_r(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target,uint8_t address, uint8_t *data) {
+ struct mpsse_context *mpsse = spi_target;
+ uint8_t out_buf[2];
+ uint8_t *in_buf = NULL;
+ int a, b;
+
+ /* check input variables */
+ CHECK_NULL(spi_target);
+ if ((address & 0x80) != 0) {
+ DEBUG_MSG("WARNING: SPI address > 127\n");
+ }
+ CHECK_NULL(data);
+
+ /* prepare frame to be sent */
+ out_buf[0] = READ_ACCESS | (address & 0x7F);
+ out_buf[1] = 0x00;
+
+ /* MPSSE transaction */
+ a = Start(mpsse);
+ in_buf = (uint8_t *)Transfer(mpsse, (char *)out_buf, 2);
+ b = Stop(mpsse);
+
+ /* determine return code */
+ if ((in_buf == NULL) || (a != MPSSE_OK) || (b != MPSSE_OK)) {
+ DEBUG_MSG("ERROR: SPI READ FAILURE\n");
+ if (in_buf != NULL) {
+ free(in_buf);
+ }
+ return LGW_SPI_ERROR;
+ } else {
+ DEBUG_MSG("Note: SPI read success\n");
+ *data = in_buf[1];
+ free(in_buf);
+ return LGW_SPI_SUCCESS;
+ }
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+/* Burst (multiple-byte) write */
+/* transaction time: 3.7ms for 2500 data bytes @6MHz, 1kB chunks */
+/* transaction time: 0.5ms for 16 data bytes @6MHz, 1kB chunks */
+int lgw_spi_wb(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target,uint8_t address, uint8_t *data, uint16_t size) {
+ struct mpsse_context *mpsse = spi_target;
+ uint8_t command;
+ uint8_t *out_buf = NULL;
+ int size_to_do, buf_size, chunk_size, offset;
+ int a=0, b=0, c=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;
+ }
+
+ /* prepare command byte */
+ command = WRITE_ACCESS | (address & 0x7F);
+ size_to_do = size + 1; /* add a byte for the address */
+
+ /* allocate data buffer */
+ buf_size = (size_to_do < LGW_BURST_CHUNK) ? size_to_do : LGW_BURST_CHUNK;
+ out_buf = malloc(buf_size);
+ if (out_buf == NULL) {
+ DEBUG_MSG("ERROR: MALLOC FAIL\n");
+ return LGW_SPI_ERROR;
+ }
+
+ /* start MPSSE transaction */
+ a = Start(mpsse);
+ for (i=0; size_to_do > 0; ++i) {
+ chunk_size = (size_to_do < LGW_BURST_CHUNK) ? size_to_do : LGW_BURST_CHUNK;
+ if (i == 0) {
+ /* first chunk, need to append the address */
+ out_buf[0] = command;
+ memcpy(out_buf+1, data, chunk_size-1);
+ } else {
+ /* following chunks, just copy the data */
+ offset = (i * LGW_BURST_CHUNK) - 1;
+ memcpy(out_buf, data + offset, chunk_size);
+ }
+ b = FastWrite(mpsse, (char *)out_buf, chunk_size);
+ size_to_do -= chunk_size; /* subtract the quantity of data already transferred */
+ }
+ c = Stop(mpsse);
+
+ /* deallocate data buffer */
+ free(out_buf);
+
+ /* determine return code (only the last FastWrite is checked) */
+ if ((a != MPSSE_OK) || (b != MPSSE_OK) || (c != MPSSE_OK)) {
+ DEBUG_MSG("ERROR: SPI BURST WRITE FAILURE\n");
+ return LGW_SPI_ERROR;
+ } else {
+ DEBUG_MSG("Note: SPI burst write success\n");
+ return LGW_SPI_SUCCESS;
+ }
+}
+
+/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+
+/* Burst (multiple-byte) read (using FastWrite & FastRead functions) */
+/* transaction time: 7-12ms for 2500 data bytes @6MHz, 1kB chunks */
+/* transaction time: 2ms for 16 data bytes @6MHz, 1kB chunks */
+int lgw_spi_rb(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target,uint8_t address, uint8_t *data, uint16_t size) {
+ struct mpsse_context *mpsse = spi_target;
+ uint8_t command;
+ int size_to_do, chunk_size, offset;
+ int a=0, b=0, c=0, d=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;
+ }
+
+ /* prepare command byte */
+ command = READ_ACCESS | (address & 0x7F);
+ size_to_do = size;
+
+ /* start MPSSE transaction */
+ a = Start(mpsse);
+ b = FastWrite(mpsse, (char *)&command, 1);
+ 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;
+ c = FastRead(mpsse, (char *)(data + offset), chunk_size);
+ size_to_do -= chunk_size; /* subtract the quantity of data already transferred */
+ }
+ d = Stop(mpsse);
+
+ /* determine return code (only the last FastRead is checked) */
+ if ((a != MPSSE_OK) || (b != MPSSE_OK) || (c != MPSSE_OK) || (d != MPSSE_OK)) {
+ DEBUG_MSG("ERROR: SPI BURST READ FAILURE\n");
+ return LGW_SPI_ERROR;
+ } else {
+ DEBUG_MSG("Note: SPI burst read success\n");
+ return LGW_SPI_SUCCESS;
+ }
+}
+
+/* --- EOF ------------------------------------------------------------------ */
diff --git a/util_lbt_test/Makefile b/util_lbt_test/Makefile
index de937e4..715e616 100644
--- a/util_lbt_test/Makefile
+++ b/util_lbt_test/Makefile
@@ -30,7 +30,7 @@ LGW_INC += $(LGW_PATH)/inc/loragw_fpga.h
### Linking options
-LIBS := -lloragw -lrt -lm
+LIBS := -lloragw -lrt -lm -lmpsse
### General build targets
diff --git a/util_pkt_logger/Makefile b/util_pkt_logger/Makefile
index 264ccc1..b156000 100644
--- a/util_pkt_logger/Makefile
+++ b/util_pkt_logger/Makefile
@@ -29,7 +29,7 @@ LGW_INC += $(LGW_PATH)/inc/loragw_hal.h
### Linking options
-LIBS := -lloragw -lrt -lm
+LIBS := -lloragw -lrt -lm -lmpsse
### General build targets
diff --git a/util_spectral_scan/Makefile b/util_spectral_scan/Makefile
index 35d625f..80264da 100644
--- a/util_spectral_scan/Makefile
+++ b/util_spectral_scan/Makefile
@@ -25,7 +25,7 @@ LGW_INC += $(LGW_PATH)/inc/loragw_hal.h
### Linking options
-LIBS := -lloragw -lrt
+LIBS := -lloragw -lrt -lmpsse
### General build targets
diff --git a/util_spi_stress/Makefile b/util_spi_stress/Makefile
index 23e3c88..2ced64a 100644
--- a/util_spi_stress/Makefile
+++ b/util_spi_stress/Makefile
@@ -30,7 +30,7 @@ LGW_INC += $(LGW_PATH)/inc/loragw_reg.h
### Linking options
-LIBS := -lloragw -lrt -lm
+LIBS := -lloragw -lrt -lm -lmpsse
### General build targets
diff --git a/util_tx_continuous/Makefile b/util_tx_continuous/Makefile
index b07419b..d5e0c5b 100644
--- a/util_tx_continuous/Makefile
+++ b/util_tx_continuous/Makefile
@@ -32,7 +32,7 @@ LGW_INC += $(LGW_PATH)/inc/loragw_aux.h
### Linking options
-LIBS := -lloragw -lrt -lm
+LIBS := -lloragw -lrt -lm -lmpsse
### General build targets
diff --git a/util_tx_test/Makefile b/util_tx_test/Makefile
index 8c35229..ab30e7f 100644
--- a/util_tx_test/Makefile
+++ b/util_tx_test/Makefile
@@ -31,7 +31,7 @@ LGW_INC += $(LGW_PATH)/inc/loragw_aux.h
### Linking options
-LIBS := -lloragw -lrt -lm
+LIBS := -lloragw -lrt -lm -lmpsse
### General build targets
--
2.28.0