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

openSUSE Build Service is sponsored by