From 60fd9788763ea11ec80ec1b1f683c0374792f71e Mon Sep 17 00:00:00 2001 From: Alexandru Caracas Date: Tue, 26 Oct 2021 11:10:22 +0200 Subject: [PATCH 1/3] fix client credentials for s2.sm.tc live test --- examples/live-s2.sm.tc/cups-boot.crt | 19 ++++++++++--------- examples/live-s2.sm.tc/cups-boot.key | 10 +++++++--- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/examples/live-s2.sm.tc/cups-boot.crt b/examples/live-s2.sm.tc/cups-boot.crt index 76b5420..a847a90 100644 --- a/examples/live-s2.sm.tc/cups-boot.crt +++ b/examples/live-s2.sm.tc/cups-boot.crt @@ -1,11 +1,12 @@ -----BEGIN CERTIFICATE----- -MIIBkzCCATmgAwIBAgIBQTAKBggqhkjOPQQDAjBXMRAwDgYDVQQDDAdSb290IENB -MSAwHgYDVQQLDBdUcmFja0NlbnRyYWwgKGVpYVBvVWM5KTEUMBIGA1UECgwLVHJh -Y2tOZXQuaW8xCzAJBgNVBAYTAkNIMB4XDTE5MDMwNzE1MjgwNVoXDTIxMDMwNjE1 -MjgwNVowTzETMBEGA1UEAwwKZ3dwcm92LTo6MDEVMBMGA1UECwwMVHJhY2tDZW50 -cmFsMRQwEgYDVQQKDAtUcmFja05ldC5pbzELMAkGA1UEBhMCQ0gwWTATBgcqhkjO -PQIBBggqhkjOPQMBBwNCAASFyfmqBPkza9kd2IkrbU3zSRIriq5vOcgwfilctZVs -j8Z7XVBMdNLjriSjchVgyBTJfvMVMbvYTdzD7w5GBSNwMAoGCCqGSM49BAMCA0gA -MEUCIQCFGgSlP6GYM6uXd6KXuEwc098p5orHP/dxupGAZifquwIgbUh9UAR8tgAi -8TH36s9z+mz27ea7ezcmH8aM4W3Meng= +MIIBlDCCATqgAwIBAgICBIcwCgYIKoZIzj0EAwIwVzEQMA4GA1UEAwwHUm9vdCBD +QTEgMB4GA1UECwwXVHJhY2tDZW50cmFsIChlaWFQb1VjOSkxFDASBgNVBAoMC1Ry +YWNrTmV0LmlvMQswCQYDVQQGEwJDSDAeFw0yMTAzMTYyMDA3MThaFw0yMzAzMTYy +MDA3MThaME8xEzARBgNVBAMMCmd3cHJvdi06OjAxFTATBgNVBAsMDFRyYWNrQ2Vu +dHJhbDEUMBIGA1UECgwLVHJhY2tOZXQuaW8xCzAJBgNVBAYTAkNIMFkwEwYHKoZI +zj0CAQYIKoZIzj0DAQcDQgAElPH25vcVjMV5WcYhTo0EM4DEj+gEeGanyo9bQRSk +4yBf90szMN2lqG2ak4TMLsiebkyUPHdd1obNrm1QRPVJ9jAKBggqhkjOPQQDAgNI +ADBFAiB1XGZZEzzenNP/NiUZ6892zgbbCth+o1CIJynx3gCZOwIhALNQMFH21Y/c ++dNexjBWotmElnRuytLVwiSq9Tnth201 -----END CERTIFICATE----- + diff --git a/examples/live-s2.sm.tc/cups-boot.key b/examples/live-s2.sm.tc/cups-boot.key index 6c00c4e..83d8620 100644 --- a/examples/live-s2.sm.tc/cups-boot.key +++ b/examples/live-s2.sm.tc/cups-boot.key @@ -1,5 +1,9 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- -----BEGIN EC PRIVATE KEY----- -MHcCAQEEIJbt0pUj24UIWS6HngUqJtP3uPpweSIqhB4TRoyHdzdqoAoGCCqGSM49 -AwEHoUQDQgAEhcn5qgT5M2vZHdiJK21N80kSK4qubznIMH4pXLWVbI/Ge11QTHTS -464ko3IVYMgUyX7zFTG72E3cw+8ORgUjcA== +MHcCAQEEIJEtcn74IfQwri/sObqTaqH0GxSyDgEBXwBkMJPSunF+oAoGCCqGSM49 +AwEHoUQDQgAElPH25vcVjMV5WcYhTo0EM4DEj+gEeGanyo9bQRSk4yBf90szMN2l +qG2ak4TMLsiebkyUPHdd1obNrm1QRPVJ9g== -----END EC PRIVATE KEY----- + From 6675c77ee7fa9bab86cc8fc2ca8a58fb106ea322 Mon Sep 17 00:00:00 2001 From: Anton Beitler Date: Thu, 6 Jan 2022 16:38:01 +0100 Subject: [PATCH 2/3] Update mbedTLS dependency to version 2.7.5. Fixes #142 --- deps/mbedtls/prep.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/mbedtls/prep.sh b/deps/mbedtls/prep.sh index 2875cd7..4f774f0 100755 --- a/deps/mbedtls/prep.sh +++ b/deps/mbedtls/prep.sh @@ -30,7 +30,7 @@ set -e cd $(dirname $0) if [[ ! -d git-repo ]]; then - git clone -b mbedtls-2.6 --single-branch --depth 1 https://github.com/ARMmbed/mbedtls.git git-repo + git clone -b mbedtls-2.7.5 --single-branch --depth 1 https://github.com/ARMmbed/mbedtls.git git-repo fi if [[ -z "$platform" ]] || [[ -z "$variant" ]]; then From ba4f85d80a438a5c2b659e568cd2d0f0de08e5a7 Mon Sep 17 00:00:00 2001 From: Anton Beitler Date: Tue, 18 Jan 2022 10:22:16 +0100 Subject: [PATCH 3/3] Release 2.0.6 * deps: Updated sx1302_hal dependency to version 2.1.0 (no LBT yet) (Resolves #89, #103, #121, #130) * deps: Added sx1302_hal patch for handling of latched xticks rollover * deps: Updated mbedTLS dependency to version 2.28.0 (LTS) * deps: Fixed lgw patch causing IQ inversion in 500kHz channel (Resolves #81) * s2e: Added support for AU915 (Resolves #43) * s2e: Added support for LoRaWAN Regional Parameters Common Names (Resolves #18) * s2e: Fixed dnchnl2 issue (Resolves #79) * s2e: Fixed class C backoff logic (Resolves #87) * s2e: Fixed class B beacon format (Resolves #129, #131) * s2e: Fixed DR range check in upchannels list parser (Resolves #141) * ral: Changed handling of xticks for lgw1302 * ral: Fixed radio in use issue (Resolves #53, #62) * ral: Fixed types in txpow assignment (master/slave) (Resolves #118) * ral: Fixed class B beacon parameters (Resolves #132) * sx130xconf: Fixed parsing of rssi_tcomp values for sx1302 (Resolves #144) * tls: Fixed TLS cert parsing issue (Resolves #76) * sys_linux: Added support for usb/spi prefix in radio devname * sys_linux: Added mbedTLS version to startup log * sys_linux: Changed version to be printed to stdout (Resolves #51) * sys_linux: Changed default max dbuf size (Resolves #95) * sys_linux: Fixed relative home path handling (Resolves #140) * sys_linux: Fixed memory corruption during system command execution (Resolves #146) * tc/cups: Fixed sync on credset file IO (Resolves #94) * timesync: Fixed UTC to PPS alignment * log: Changed verbosity of XDEBUG log level * log: Changed logging experience for improved clarity * log: Added HAL log integration into logging module * make: Changed makefiles for more space-friendliness (Resolves #66) * net: Changed strictness on line-endings in key files (Resolves #68) * gps: Fixed parsing of ublox NAV-TIMEGPS message * Restored LICENSE file (Resolves #63, #67) --- .github/workflows/regr-tests.yml | 32 + .travis.yml | 18 - CHANGELOG.md | 54 +- LICENSE | 25 + README.md | 6 +- SECURITY.md | 15 - VERSION.txt | 2 +- deps/lgw/makefile | 18 +- deps/lgw/prep.sh | 2 +- deps/lgw/v5.0.1-kerlink.patch | 1058 ++++++++- deps/lgw/v5.0.1-linux.patch | 1058 ++++++++- deps/lgw/v5.0.1-rpi.patch | 1058 ++++++++- deps/lgw1302/V1.0.5-corecell.patch | 300 --- deps/lgw1302/V2.1.0-corecell.patch | 2827 +++++++++++++++++++++++ deps/lgw1302/makefile | 10 +- deps/lgw1302/prep.sh | 4 +- deps/mbedtls/makefile | 6 +- deps/mbedtls/prep.sh | 4 +- deps/smtcpico/V0.2.2-linuxpico.patch | 1239 +++++++++- deps/smtcpico/makefile | 10 +- deps/smtcpico/prep.sh | 2 +- examples/corecell/start-station.sh | 2 +- examples/cups/emulate.sh | 2 +- examples/cups/makefile | 2 +- examples/cups/prep.sh | 2 +- examples/cups/requirements.txt | 4 +- examples/cups/sim.py | 2 +- examples/live-s2.sm.tc/makefile | 2 +- examples/simulation/makefile | 2 +- examples/simulation/requirements.txt | 4 +- examples/simulation/sim.py | 2 +- examples/station2pkfwd/bgtask.py | 2 +- examples/station2pkfwd/id6.py | 2 +- examples/station2pkfwd/main.py | 2 +- examples/station2pkfwd/pkfwdc.py | 2 +- examples/station2pkfwd/requirements.txt | 4 +- examples/station2pkfwd/router.py | 2 +- examples/station2pkfwd/router_config.py | 2 +- makefile | 2 +- makefile.s2core | 2 +- pysys/id6.py | 2 +- pysys/simutils.py | 2 +- pysys/tcutils.py | 36 +- pysys/testutils.py | 2 +- regr-tests/makefile | 11 +- regr-tests/run-regression-tests | 21 +- regr-tests/test1-selftests/makefile | 2 +- regr-tests/test1-selftests/test.sh | 2 +- regr-tests/test2-fs/makefile | 2 +- regr-tests/test2-fs/test.sh | 2 +- regr-tests/test2-gps/makefile | 2 +- regr-tests/test2-gps/test.py | 14 +- regr-tests/test2-gps/test.sh | 2 +- regr-tests/test2-pps/makefile | 2 +- regr-tests/test2-pps/test.py | 10 +- regr-tests/test2-pps/test.sh | 2 +- regr-tests/test3-updn-tls/makefile | 2 +- regr-tests/test3-updn-tls/test.py | 12 +- regr-tests/test3-updn-tls/test.sh | 2 +- regr-tests/test3a-updn-tls/makefile | 2 +- regr-tests/test3a-updn-tls/test.py | 12 +- regr-tests/test3a-updn-tls/test.sh | 2 +- regr-tests/test3b-dnC/makefile | 2 +- regr-tests/test3b-dnC/test.py | 7 +- regr-tests/test3b-dnC/test.sh | 2 +- regr-tests/test3b-dnC_2ant/makefile | 2 +- regr-tests/test3b-dnC_2ant/test.py | 5 +- regr-tests/test3b-dnC_2ant/test.sh | 2 +- regr-tests/test3b-rx2_2ant/makefile | 2 +- regr-tests/test3b-rx2_2ant/test.py | 2 +- regr-tests/test3b-rx2_2ant/test.sh | 2 +- regr-tests/test3c-cca/makefile | 2 +- regr-tests/test3c-cca/test.py | 6 +- regr-tests/test3c-cca/test.sh | 2 +- regr-tests/test3d-bcns/makefile | 2 +- regr-tests/test3d-bcns/test.py | 7 +- regr-tests/test3d-bcns/test.sh | 2 +- regr-tests/test4-cups/makefile | 2 +- regr-tests/test4-cups/test.py | 2 +- regr-tests/test4-cups/test.sh | 2 +- regr-tests/test5-rmtsh/makefile | 2 +- regr-tests/test5-rmtsh/test.py | 2 +- regr-tests/test5-rmtsh/test.sh | 2 +- regr-tests/test5-runcmd/makefile | 2 +- regr-tests/test5-runcmd/test.py | 2 +- regr-tests/test5-runcmd/test.sh | 2 +- regr-tests/test7-respawn/makefile | 2 +- regr-tests/test7-respawn/test.sh | 2 +- regr-tests/test8-web/makefile | 2 +- regr-tests/test8-web/tc.uri | 2 +- regr-tests/test8-web/test.sh | 83 +- regr-tests/testlib.sh | 2 +- setup.gmk | 6 +- src-linux/cmdfifo.c | 10 +- src-linux/commands.c | 2 +- src-linux/gps.c | 120 +- src-linux/leds.c | 2 +- src-linux/ral_master.c | 4 +- src-linux/ral_slave.c | 70 +- src-linux/ralsub.h | 5 +- src-linux/rmtsh.c | 2 +- src-linux/station_main.c | 2 +- src-linux/sys_linux.c | 72 +- src-linux/sys_linux.h | 2 +- src-linux/sys_log.c | 2 +- src-linux/web_linux.c | 2 +- src/aio.c | 2 +- src/argp.c | 2 +- src/argp2.h | 2 +- src/crc32.c | 2 +- src/cups.c | 30 +- src/cups.h | 2 +- src/flashsim.c | 2 +- src/fs.c | 9 +- src/fs.h | 23 +- src/genkwcrcs.c | 11 +- src/http.h | 2 +- src/httpd.h | 2 +- src/kwcrc.h | 3 + src/kwlist.txt | 3 + src/lgwsim.c | 3 +- src/log.c | 11 +- src/lora.c | 6 +- src/net.c | 66 +- src/net.h | 2 +- src/ral.c | 2 +- src/ral.h | 2 +- src/ral_lgw.c | 94 +- src/ral_lgw2.c | 26 +- src/rt.c | 8 +- src/rt.h | 10 +- src/s2conf.c | 2 +- src/s2conf.h | 2 +- src/s2e.c | 177 +- src/s2e.h | 11 +- src/selftest_fs.c | 2 +- src/selftest_lora.c | 2 +- src/selftest_rt.c | 2 +- src/selftest_ujdec.c | 22 +- src/selftest_ujenc.c | 2 +- src/selftest_xprintf.c | 2 +- src/selftest_xq.c | 2 +- src/selftests.c | 2 +- src/selftests.h | 2 +- src/sx1301v2conf.c | 23 +- src/sx1301v2conf.h | 2 +- src/sx130xconf.c | 259 ++- src/sx130xconf.h | 2 +- src/sys.c | 23 +- src/sys.h | 5 +- src/tc.c | 8 +- src/tc.h | 2 +- src/timesync.c | 39 +- src/timesync.h | 2 +- src/tls.c | 10 +- src/tls.h | 2 +- src/uj.c | 2 +- src/uj.h | 2 +- src/web.c | 4 +- src/web.h | 2 +- src/ws.h | 2 +- src/xq.c | 2 +- src/xq.h | 2 +- 163 files changed, 8165 insertions(+), 1180 deletions(-) create mode 100644 .github/workflows/regr-tests.yml delete mode 100644 .travis.yml create mode 100644 LICENSE delete mode 100644 SECURITY.md delete mode 100644 deps/lgw1302/V1.0.5-corecell.patch create mode 100644 deps/lgw1302/V2.1.0-corecell.patch diff --git a/.github/workflows/regr-tests.yml b/.github/workflows/regr-tests.yml new file mode 100644 index 0000000..b5acc6e --- /dev/null +++ b/.github/workflows/regr-tests.yml @@ -0,0 +1,32 @@ +name: regr-tests +on: [push] +jobs: + run-regr-tests: + runs-on: ubuntu-18.04 + steps: + - name: Checkout repo + uses: actions/checkout@v2 + - name: Setup environment + run: | + sudo apt-get install -y python3.7 python3-pip virtualenv psmisc git build-essential lcov curl netcat-openbsd + virtualenv --python python3.7 pyenv + . pyenv/bin/activate + pip3 install setuptools aiohttp websockets + - name: Execute Tests + run: | + # relax some regr test success conditions - related to timing + . pyenv/bin/activate + export PPSTHRES=100 + export TX_AIM_GAP='"40ms"' + make -C regr-tests ci s2core.info + - name: Archive logs + uses: actions/upload-artifact@v2 + with: + name: Test logs + path: regr-tests/t.log/*.log + - name: Archive Coverage report + uses: actions/upload-artifact@v2 + with: + name: Coverage report + path: regr-tests/s2core-html/** + diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e4aff84..0000000 --- a/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -language: minimal - -services: docker - -env: Dimg=lorabasics; Dname=basicstation-test - -before_install: -- sudo chown -R 1000:1000 $TRAVIS_BUILD_DIR -- docker build . -t $Dimg -- docker run --init -d --name $Dname -v $TRAVIS_BUILD_DIR:/home/nonprivuser/travis -w /home/nonprivuser/travis $Dimg tail -f /dev/null -- export Dcmd="docker exec -t $Dname bash -c" - -install: -# nothing to install - -script: -# all commands must be quoted -- $Dcmd "make -C regr-tests ci s2core.info" diff --git a/CHANGELOG.md b/CHANGELOG.md index 70d0e41..fab4b2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,26 +1,60 @@ # Changelog +## 2.0.6 - 2022-01-17 + +* deps: Updated sx1302_hal dependency to version 2.1.0 (no LBT yet) (#89, #103, #121, #130) +* deps: Added sx1302_hal patch for handling of latched xticks rollover +* deps: Updated mbedTLS dependency to version 2.28.0 (LTS) +* deps: Fixed lgw patch causing IQ inversion in 500kHz channel (#81) +* s2e: Added support for AU915 (#43) +* s2e: Added support for LoRaWAN Regional Parameters Common Names (#18) +* s2e: Fixed dnchnl2 issue (#79) +* s2e: Fixed class C backoff logic (#87) +* s2e: Fixed class B beacon format (#129, #131) +* s2e: Fixed DR range check in upchannels list parser (#141) +* ral: Changed handling of xticks for lgw1302 +* ral: Fixed radio in use issue (#53, #62) +* ral: Fixed types in txpow assignment (master/slave) (#118) +* ral: Fixed class B beacon parameters (#132) +* sx130xconf: Fixed parsing of rssi_tcomp values for sx1302 (#144) +* tls: Fixed TLS cert parsing issue (#76) +* sys_linux: Added support for usb/spi prefix in radio devname +* sys_linux: Added mbedTLS version to startup log +* sys_linux: Changed version to be printed to stdout (#51) +* sys_linux: Changed default max dbuf size (#95) +* sys_linux: Fixed relative home path handling (#140) +* sys_linux: Fixed memory corruption during system command execution (#146) +* tc/cups: Fixed sync on credset file IO (#94) +* timesync: Fixed UTC to PPS alignment +* log: Changed verbosity of XDEBUG log level +* log: Changed logging experience for improved clarity +* log: Added HAL log integration into logging module +* make: Changed makefiles for more space-friendliness (#66) +* net: Changed strictness on line-endings in key files (#68) +* gps: Fixed parsing of ublox NAV-TIMEGPS message +* Restored LICENSE file (#63, #67) + ## 2.0.5 - 2020-06-05 -* README.md - Updated with supported platform and Travis Banner + * Remove LICENSE & ROADMAP.md file * Based on v2.0.4 with no source code/functional changes ## 2.0.4 - 2020-03-17 -* cups - Add Content-Type header to CUPS request -* sys_linux - truncate update file instead of append -* cups - nullify sig pointer after free -* cups - symbol for signature crc length -* cups - Add segment length checks -* sys_linux - cups update abort should unlink the right file -* cups - free the key buffer -* lgw1302: Added sx1302 hal and integrated with corecell platform + +* cups: Added Content-Type header to CUPS request +* cups: Fixed nullify sig pointer after free +* cups: Added segment length checks +* cups: Fixed freeing the key buffer +* deps: Added sx1302 hal and integrated with corecell platform * sys_linux: Fixed decoder pointer dereferencing (#39) +* sys_linux: Fixed cups update abort should unlink the right file +* sys_linux: Fixed truncate update file instead of append * s2e: Fixed memory corruption bug in JoinEui filter parsing (#31) * s2e: Added DR and Freq fields to dntxed message (#37) * s2e: Added error message type for printing LNS error into Station's log (#33) * s2e: Added fts field to updf message * net: Added Websocket PONG (#29) -* net: Added option for TLS server name indication/verification +* net: Added option for TLS server name indication/verification (#57) * rt: Added MCU clock drift compensation for UTC time offset * ral: Fixed dntxed message for short transmissions * ral: Added Automatic channel allocation feature diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ec8be3b --- /dev/null +++ b/LICENSE @@ -0,0 +1,25 @@ +--- Revised 3-Clause BSD License --- +Copyright Semtech Corporation 2022. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the Semtech corporation nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION. BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md index 78d8970..4cfc0f2 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Build Status](https://travis-ci.com/lorabasics/basicstation.svg?branch=master)](https://travis-ci.com/lorabasics/basicstation) +[![regr-tests](https://github.com/lorabasics/basicstation/actions/workflows/regr-tests.yml/badge.svg?branch=master)](https://github.com/lorabasics/basicstation/actions/workflows/regr-tests.yml?query=branch%3Amaster) # LoRa Basics™ Station @@ -40,7 +40,7 @@ Building the Station binary from source, requires ## First Steps -The following is a three-step quick start guide on how to build and run Station. It uses a Raspberry Pi as host platform and assumes a Concentrator Reference Design 1.5 compatible radio board connected via SPI. In this example the build process is done on the target platform itself (the make environment also supports cross compilation in which case the toolchain is expected in `~/toolchain-$platform` - see [setup.gmk](setup.gmk)). +The following is a three-step quick start guide on how to build and run Station. It uses a Raspberry Pi as host platform and assumes a Concentrator Reference Design 1.5 compatible radio board connected via SPI, and assumes that SPI port is enabled using the [raspi-config](https://www.raspberrypi.org/documentation/configuration/raspi-config.md) tool. In this example the build process is done on the target platform itself (the make environment also supports cross compilation in which case the toolchain is expected in `~/toolchain-$platform` - see [setup.gmk](setup.gmk)). #### Step 1: Cloning the Station Repository @@ -87,6 +87,8 @@ cd examples/corecell This example configuration for Corecell connects to [The Things Network](https://www.thethingsnetwork.org/) public LNS. The example [station.conf](station.conf) file holds the required radio configurations and station fetches the channel plan from the configured LNS url ([tc.uri](tc.uri)). +Note: SPI port requires to be activated on Raspberry Pi thanks to [raspi-config](https://www.raspberrypi.org/documentation/configuration/raspi-config.md) tool. + #### PicoCell Gateway (Linux OS as HOST + [SX1308 USB Reference design](https://www.semtech.com/products/wireless-rf/lora-gateways/sx1308p868gw)) diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index aeb8d52..0000000 --- a/SECURITY.md +++ /dev/null @@ -1,15 +0,0 @@ -# Security Policy - -## Supported Versions - -Vulnerability fixes will be included in next release. -Older releases will not be hotfixed. - -| Version | Supported | -| ------- | ------------------ | -| [latest release](https://github.com/lorabasics/basicstation/releases/latest) | :white_check_mark: | -| older releases | :x: | - -## Reporting a Vulnerability - -Please report security concerns, perceived or implemented vulnerabilities in the source code of this project to: [LoRa-Net@semtech.com](mailto:LoRa-Net@semtech.com) diff --git a/VERSION.txt b/VERSION.txt index e010258..157e54f 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -2.0.5 +2.0.6 diff --git a/deps/lgw/makefile b/deps/lgw/makefile index a7e93c6..0e46988 100644 --- a/deps/lgw/makefile +++ b/deps/lgw/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -35,10 +35,14 @@ LGWVERSION.default = 5.0.1 LGWVERSION ?= $(or ${LGWVERSION.${platform}}, ${LGWVERSION.default}) HFILES = $(wildcard ${PLT}/libloragw/inc/*.h) -SRCS = $(wildcard ${PLT}/libloragw/inc/*.c) +SRCS = $(wildcard ${PLT}/libloragw/src/*.c) ARTEFACTS = ${LGWLIB} ${LGWINC} $(patsubst %, ${LGWINC}/%, $(notdir ${HFILES}) config.h) -all: $(if ${HFILES},${ARTEFACTS},${PLT}) +LGW_EXTRA_CFLAGS = -DSTATIONLOG # Enable station log integration + +all: platform build +platform: ${PLT} +build: ${ARTEFACTS} ${LGWINC}: @mkdir -p $@ @@ -49,10 +53,10 @@ ${LGWLIB}: ${PLT}/libloragw/libloragw.a @cp $< $@ ${PLT}/libloragw/libloragw.a: ${SRCS} ${HFILES} - ${MAKE} -C ${PLT}/libloragw libloragw.a CC=${CC} AR=${AR} LD=${LD} TDfull=${TDfull} + ${MAKE} -C ${PLT}/libloragw libloragw.a CC="${CC}" AR="${AR}" LD="${LD}" TDfull="${TDfull}" EXTRA_CFLAGS="${LGW_EXTRA_CFLAGS}" ${PLT}/libloragw/inc/config.h: ${PLT}/libloragw/library.cfg - ${MAKE} -C ${PLT}/libloragw inc/config.h CC=${CC} AR=${AR} LD=${LD} TDfull=${TDfull} + ${MAKE} -C ${PLT}/libloragw inc/config.h CC="${CC}" AR="${AR}" LD="${LD}" TDfull="${TDfull}" ${LGWINC}/%.h: ${PLT}/libloragw/inc/%.h | ${LGWINC} @echo " CP ${ $@" @@ -60,7 +64,7 @@ ${LGWINC}/%.h: ${PLT}/libloragw/inc/%.h | ${LGWINC} ${PLT}: prep.sh platform=${platform} variant=${variant} lgwversion=${LGWVERSION} ./prep.sh - $(MAKE) --no-print-directory all platform=${platform} variant=${variant} + $(MAKE) --no-print-directory build platform=${platform} variant=${variant} clean: rm -rf ${ARTEFACTS} @@ -69,4 +73,4 @@ clean: super-clean: clean rm -rf git-repo platform-* -.PHONY: all clean super-clean platform-${platform} \ No newline at end of file +.PHONY: all build clean platform super-clean diff --git a/deps/lgw/prep.sh b/deps/lgw/prep.sh index 53cc788..bd4d54f 100755 --- a/deps/lgw/prep.sh +++ b/deps/lgw/prep.sh @@ -1,7 +1,7 @@ #!/bin/bash # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/deps/lgw/v5.0.1-kerlink.patch b/deps/lgw/v5.0.1-kerlink.patch index 8a2281b..3c1aaf6 100644 --- a/deps/lgw/v5.0.1-kerlink.patch +++ b/deps/lgw/v5.0.1-kerlink.patch @@ -1,15 +1,20 @@ diff --git a/libloragw/Makefile b/libloragw/Makefile -index 53c33d9..a8a09a2 100644 +index 53c33d9..cc7d016 100644 --- a/libloragw/Makefile +++ b/libloragw/Makefile -@@ -7,6 +7,7 @@ include library.cfg - +@@ -7,10 +7,12 @@ include library.cfg + ARCH ?= CROSS_COMPILE ?= + CC := $(CROSS_COMPILE)gcc AR := $(CROSS_COMPILE)ar - + + CFLAGS := -O2 -Wall -Wextra -std=c99 -Iinc -I. ++CFLAGS += ${EXTRA_CFLAGS} + + OBJDIR = obj + INCLUDES = $(wildcard inc/*.h) diff --git a/libloragw/inc/loragw_hal.h b/libloragw/inc/loragw_hal.h index d5f9ade..57927c4 100644 --- a/libloragw/inc/loragw_hal.h @@ -17,7 +22,7 @@ index d5f9ade..57927c4 100644 @@ -414,6 +414,12 @@ const char* lgw_version_info(void); */ uint32_t lgw_time_on_air(struct lgw_pkt_tx_s *packet); - + +extern uint8_t lgwx_device_mode; +extern uint8_t lgwx_beacon_len; +extern uint8_t lgwx_beacon_sf; @@ -25,109 +30,1070 @@ index d5f9ade..57927c4 100644 +enum { LGWX_LBT_MODE_DFLT=0, LGWX_LBT_MODE_OFF = 1 }; + #endif - + /* --- EOF ------------------------------------------------------------------ */ +diff --git a/libloragw/inc/loragw_stationlog.h b/libloragw/inc/loragw_stationlog.h +new file mode 100644 +index 0000000..a282b8f +--- /dev/null ++++ b/libloragw/inc/loragw_stationlog.h +@@ -0,0 +1,26 @@ ++#ifndef _LORAGW_STATIONLOG_H ++#define _LORAGW_STATIONLOG_H ++ ++#if defined(STATIONLOG) ++ ++#undef DEBUG_PRINTF ++#undef DEBUG_MSG ++ ++enum { XDEBUG=0, DEBUG, VERBOSE, INFO, NOTICE, WARNING, ERROR, CRITICAL }; ++extern void log_hal (uint8_t level, const char* fmt, ...); ++#define ERROR_PRINTF(fmt, ...) log_hal(ERROR , "[%s:%d] "fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__) ++#define INFO_PRINTF(fmt, ...) log_hal(INFO , "[%s:%d] "fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__) ++#define DEBUG_PRINTF(fmt, ...) log_hal(XDEBUG , "[%s:%d] "fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__) ++#define DEBUG_MSG(str) log_hal(XDEBUG , "[%s:%d] %s", __FUNCTION__, __LINE__, str) ++#define XDEBUG_PRINTF(fmt, ...) log_hal(XDEBUG , "[%s:%d] "fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__) ++#define XDEBUG_MSG(str) log_hal(XDEBUG , "[%s:%d] %s", __FUNCTION__, __LINE__, str) ++ ++#else // !defined(STATIONLOG) ++ ++#define ERROR_PRINTF(fmt, ...) DEBUG_PRINTF(fmt, ## __VA_ARGS__) ++#define INFO_PRINTF(fmt, ...) DEBUG_PRINTF(fmt, ## __VA_ARGS__) ++#define XDEBUG_PRINTF(fmt, ...) DEBUG_PRINTF(fmt, ## __VA_ARGS__) ++#define XDEBUG_MSG(str) DEBUG_MSG(str) ++#endif ++ ++#endif +diff --git a/libloragw/src/loragw_fpga.c b/libloragw/src/loragw_fpga.c +index 465f43e..9b98786 100644 +--- a/libloragw/src/loragw_fpga.c ++++ b/libloragw/src/loragw_fpga.c +@@ -43,6 +43,8 @@ Maintainer: Michael Coracin + #define CHECK_NULL(a) if(a==NULL){return LGW_REG_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + +@@ -140,21 +142,16 @@ int lgw_fpga_configure(uint32_t tx_notch_freq) { + } + + /* Get supported FPGA features */ +- printf("INFO: FPGA supported features:"); + lgw_fpga_reg_r(LGW_FPGA_FEATURE, &val); + tx_notch_support = TAKE_N_BITS_FROM((uint8_t)val, 0, 1); +- if (tx_notch_support == true) { +- printf(" [TX filter] "); +- } + spectral_scan_support = TAKE_N_BITS_FROM((uint8_t)val, 1, 1); +- if (spectral_scan_support == true) { +- printf(" [Spectral Scan] "); +- } + lbt_support = TAKE_N_BITS_FROM((uint8_t)val, 2, 1); +- if (lbt_support == true) { +- printf(" [LBT] "); +- } +- printf("\n"); ++ ++ INFO_PRINTF("INFO: FPGA supported features: %s%s%s", ++ tx_notch_support ? " [TX filter] " : "", ++ spectral_scan_support ? " [Spectral Scan] " : "", ++ lbt_support ? " [lbt_support] " : "" ++ ); + + x = lgw_fpga_reg_w(LGW_FPGA_CTRL_INPUT_SYNC_I, 1); + x |= lgw_fpga_reg_w(LGW_FPGA_CTRL_INPUT_SYNC_Q, 1); +diff --git a/libloragw/src/loragw_gps.c b/libloragw/src/loragw_gps.c +index c0e0ded..14eff6e 100644 +--- a/libloragw/src/loragw_gps.c ++++ b/libloragw/src/loragw_gps.c +@@ -39,16 +39,20 @@ Maintainer: Michael Coracin + + #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + #if DEBUG_GPS == 1 +- #define DEBUG_MSG(args...) fprintf(stderr, args) ++ #define DEBUG_MSG(str) fprintf(stderr, str) ++ #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args) + #define DEBUG_ARRAY(a,b,c) for(a=0;a %H", buff_size, serial_buff); ++#else + DEBUG_MSG("Note: parsing UBX frame> "); + for (i=0; i= LGW_RF_CHAIN_NB) { +- DEBUG_MSG("ERROR: NOT A VALID RF_CHAIN NUMBER\n"); ++ ERROR_PRINTF("NOT A VALID RF_CHAIN NUMBER\n"); + return LGW_HAL_ERROR; + } + + /* check if radio type is supported */ + if ((conf.type != LGW_RADIO_TYPE_SX1255) && (conf.type != LGW_RADIO_TYPE_SX1257)) { +- DEBUG_MSG("ERROR: NOT A VALID RADIO TYPE\n"); ++ ERROR_PRINTF("NOT A VALID RADIO TYPE\n"); + return LGW_HAL_ERROR; + } + +@@ -498,13 +524,13 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + + /* check if the concentrator is running */ + if (lgw_is_started == true) { +- DEBUG_MSG("ERROR: CONCENTRATOR IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); ++ ERROR_PRINTF("CONCENTRATOR IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); + return LGW_HAL_ERROR; + } + + /* check input range (segfault prevention) */ + if (if_chain >= LGW_IF_CHAIN_NB) { +- DEBUG_PRINTF("ERROR: %d NOT A VALID IF_CHAIN NUMBER\n", if_chain); ++ ERROR_PRINTF("%d NOT A VALID IF_CHAIN NUMBER\n", if_chain); + return LGW_HAL_ERROR; + } + +@@ -518,10 +544,10 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + + /* check 'general' parameters */ + if (ifmod_config[if_chain] == IF_UNDEFINED) { +- DEBUG_PRINTF("ERROR: IF CHAIN %d NOT CONFIGURABLE\n", if_chain); ++ ERROR_PRINTF("IF CHAIN %d NOT CONFIGURABLE\n", if_chain); + } + if (conf.rf_chain >= LGW_RF_CHAIN_NB) { +- DEBUG_MSG("ERROR: INVALID RF_CHAIN TO ASSOCIATE WITH A LORA_STD IF CHAIN\n"); ++ ERROR_PRINTF("INVALID RF_CHAIN TO ASSOCIATE WITH A LORA_STD IF CHAIN\n"); + return LGW_HAL_ERROR; + } + /* check if IF frequency is optimal based on channel and radio bandwidths */ +@@ -539,10 +565,10 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + } + bw_hz = lgw_bw_getval(conf.bandwidth); /* channel bandwidth */ + if ((conf.freq_hz + ((bw_hz==-1)?LGW_REF_BW:bw_hz)/2) > ((int32_t)rf_rx_bandwidth/2)) { +- DEBUG_PRINTF("ERROR: IF FREQUENCY %d TOO HIGH\n", conf.freq_hz); ++ ERROR_PRINTF("IF FREQUENCY %d TOO HIGH\n", conf.freq_hz); + return LGW_HAL_ERROR; + } else if ((conf.freq_hz - ((bw_hz==-1)?LGW_REF_BW:bw_hz)/2) < -((int32_t)rf_rx_bandwidth/2)) { +- DEBUG_PRINTF("ERROR: IF FREQUENCY %d TOO LOW\n", conf.freq_hz); ++ ERROR_PRINTF("IF FREQUENCY %d TOO LOW\n", conf.freq_hz); + return LGW_HAL_ERROR; + } + +@@ -559,11 +585,11 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + } + /* check BW & DR */ + if (!IS_LORA_BW(conf.bandwidth)) { +- DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA_STD IF CHAIN\n"); ++ ERROR_PRINTF("BANDWIDTH NOT SUPPORTED BY LORA_STD IF CHAIN\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_STD_DR(conf.datarate)) { +- DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY LORA_STD IF CHAIN\n"); ++ ERROR_PRINTF("DATARATE NOT SUPPORTED BY LORA_STD IF CHAIN\n"); + return LGW_HAL_ERROR; + } + /* set internal configuration */ +@@ -591,11 +617,11 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + } + /* check BW & DR */ + if (conf.bandwidth != BW_125KHZ) { +- DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); ++ ERROR_PRINTF("BANDWIDTH NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_MULTI_DR(conf.datarate)) { +- DEBUG_MSG("ERROR: DATARATE(S) NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); ++ ERROR_PRINTF("DATARATE(S) NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); + return LGW_HAL_ERROR; + } + /* set internal configuration */ +@@ -617,11 +643,11 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + } + /* check BW & DR */ + if(!IS_FSK_BW(conf.bandwidth)) { +- DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY FSK IF CHAIN\n"); ++ ERROR_PRINTF("BANDWIDTH NOT SUPPORTED BY FSK IF CHAIN\n"); + return LGW_HAL_ERROR; + } + if(!IS_FSK_DR(conf.datarate)) { +- DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); ++ ERROR_PRINTF("DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); + return LGW_HAL_ERROR; + } + /* set internal configuration */ +@@ -638,7 +664,7 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + break; + + default: +- DEBUG_PRINTF("ERROR: IF CHAIN %d TYPE NOT SUPPORTED\n", if_chain); ++ ERROR_PRINTF("IF CHAIN %d TYPE NOT SUPPORTED\n", if_chain); + return LGW_HAL_ERROR; + } + +@@ -652,7 +678,7 @@ int lgw_txgain_setconf(struct lgw_tx_gain_lut_s *conf) { + + /* Check LUT size */ + if ((conf->size < 1) || (conf->size > TX_GAIN_LUT_SIZE_MAX)) { +- DEBUG_PRINTF("ERROR: TX gain LUT must have at least one entry and maximum %d entries\n", TX_GAIN_LUT_SIZE_MAX); ++ ERROR_PRINTF("TX gain LUT must have at least one entry and maximum %d entries\n", TX_GAIN_LUT_SIZE_MAX); + return LGW_HAL_ERROR; + } + +@@ -661,22 +687,22 @@ int lgw_txgain_setconf(struct lgw_tx_gain_lut_s *conf) { + for (i = 0; i < txgain_lut.size; i++) { + /* Check gain range */ + if (conf->lut[i].dig_gain > 3) { +- DEBUG_MSG("ERROR: TX gain LUT: SX1301 digital gain must be between 0 and 3\n"); ++ ERROR_PRINTF("TX gain LUT: SX1301 digital gain must be between 0 and 3\n"); + return LGW_HAL_ERROR; + } + if (conf->lut[i].dac_gain != 3) { +- DEBUG_MSG("ERROR: TX gain LUT: SX1257 DAC gains != 3 are not supported\n"); ++ ERROR_PRINTF("TX gain LUT: SX1257 DAC gains != 3 are not supported\n"); + return LGW_HAL_ERROR; + } + if (conf->lut[i].mix_gain > 15) { +- DEBUG_MSG("ERROR: TX gain LUT: SX1257 mixer gain must not exceed 15\n"); ++ ERROR_PRINTF("TX gain LUT: SX1257 mixer gain must not exceed 15\n"); + return LGW_HAL_ERROR; + } else if (conf->lut[i].mix_gain < 8) { +- DEBUG_MSG("ERROR: TX gain LUT: SX1257 mixer gains < 8 are not supported\n"); ++ ERROR_PRINTF("TX gain LUT: SX1257 mixer gains < 8 are not supported\n"); + return LGW_HAL_ERROR; + } + if (conf->lut[i].pa_gain > 3) { +- DEBUG_MSG("ERROR: TX gain LUT: External PA gain must not exceed 3\n"); ++ ERROR_PRINTF("TX gain LUT: External PA gain must not exceed 3\n"); + return LGW_HAL_ERROR; + } + +@@ -713,7 +739,7 @@ int lgw_start(void) { + + reg_stat = lgw_connect(false, rf_tx_notch_freq[rf_tx_enable[1]?1:0]); + if (reg_stat == LGW_REG_ERROR) { +- DEBUG_MSG("ERROR: FAIL TO CONNECT BOARD\n"); ++ ERROR_PRINTF("FAIL TO CONNECT BOARD\n"); + return LGW_HAL_ERROR; + } + +@@ -735,12 +761,12 @@ int lgw_start(void) { + /* setup the radios */ + err = lgw_setup_sx125x(0, rf_clkout, rf_enable[0], rf_radio_type[0], rf_rx_freq[0]); + if (err != 0) { +- DEBUG_MSG("ERROR: Failed to setup sx125x radio for RF chain 0\n"); ++ ERROR_PRINTF("Failed to setup sx125x radio for RF chain 0\n"); + return LGW_HAL_ERROR; + } + err = lgw_setup_sx125x(1, rf_clkout, rf_enable[1], rf_radio_type[1], rf_rx_freq[1]); + if (err != 0) { +- DEBUG_MSG("ERROR: Failed to setup sx125x radio for RF chain 0\n"); ++ ERROR_PRINTF("Failed to setup sx125x radio for RF chain 0\n"); + return LGW_HAL_ERROR; + } + +@@ -753,7 +779,7 @@ int lgw_start(void) { + lgw_reg_w(LGW_CLK32M_EN, 1); + i = lbt_setup(); + if (i != LGW_LBT_SUCCESS) { +- DEBUG_MSG("ERROR: lbt_setup() did not return SUCCESS\n"); ++ ERROR_PRINTF("lbt_setup() did not return SUCCESS\n"); + return LGW_HAL_ERROR; + } + +@@ -761,7 +787,7 @@ int lgw_start(void) { + lgw_reg_w(LGW_CLK32M_EN, 0); + i = lbt_start(); + if (i != LGW_LBT_SUCCESS) { +- DEBUG_MSG("ERROR: lbt_start() did not return SUCCESS\n"); ++ ERROR_PRINTF("lbt_start() did not return SUCCESS\n"); + return LGW_HAL_ERROR; + } + } +@@ -794,7 +820,7 @@ int lgw_start(void) { + cal_cmd |= 0x00; /* Bit 5: 0: SX1257, 1: SX1255 */ + break; + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type[0]); ++ ERROR_PRINTF("UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type[0]); + break; + } + +@@ -812,7 +838,7 @@ int lgw_start(void) { + lgw_reg_r(LGW_DBG_AGC_MCU_RAM_DATA, &read_val); + fw_version = (uint8_t)read_val; + if (fw_version != FW_VERSION_CAL) { +- printf("ERROR: Version of calibration firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_CAL); ++ ERROR_PRINTF("Version of calibration firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_CAL); + return -1; + } + +@@ -838,7 +864,7 @@ int lgw_start(void) { + bit 6: radio B TX DC Offset correction successful + */ + if ((cal_status & 0x81) != 0x81) { +- DEBUG_PRINTF("ERROR: CALIBRATION FAILURE (STATUS = %u)\n", cal_status); ++ ERROR_PRINTF("CALIBRATION FAILURE (STATUS = %u)\n", cal_status); + return LGW_HAL_ERROR; + } else { + DEBUG_PRINTF("Note: calibration finished (status = %u)\n", cal_status); +@@ -883,7 +909,7 @@ int lgw_start(void) { + + /* Sanity check for RX frequency */ + if (rf_rx_freq[0] == 0) { +- DEBUG_MSG("ERROR: wrong configuration, rf_rx_freq[0] is not set\n"); ++ ERROR_PRINTF("wrong configuration, rf_rx_freq[0] is not set\n"); + return LGW_HAL_ERROR; + } + +@@ -939,7 +965,7 @@ int lgw_start(void) { + case BW_250KHZ: lgw_reg_w(LGW_MBWSSF_MODEM_BW, 1); break; + case BW_500KHZ: lgw_reg_w(LGW_MBWSSF_MODEM_BW, 2); break; + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", lora_rx_bw); ++ ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", lora_rx_bw); + return LGW_HAL_ERROR; + } + switch(lora_rx_sf) { +@@ -950,7 +976,7 @@ int lgw_start(void) { + case DR_LORA_SF11: lgw_reg_w(LGW_MBWSSF_RATE_SF, 11); break; + case DR_LORA_SF12: lgw_reg_w(LGW_MBWSSF_RATE_SF, 12); break; + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", lora_rx_sf); ++ ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", lora_rx_sf); + return LGW_HAL_ERROR; + } + lgw_reg_w(LGW_MBWSSF_PPM_OFFSET, lora_rx_ppm_offset); /* default 0 */ +@@ -994,14 +1020,14 @@ int lgw_start(void) { + lgw_reg_r(LGW_DBG_AGC_MCU_RAM_DATA, &read_val); + fw_version = (uint8_t)read_val; + if (fw_version != FW_VERSION_AGC) { +- DEBUG_PRINTF("ERROR: Version of AGC firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_AGC); ++ ERROR_PRINTF("Version of AGC firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_AGC); + return LGW_HAL_ERROR; + } + lgw_reg_w(LGW_DBG_ARB_MCU_RAM_ADDR, FW_VERSION_ADDR); + lgw_reg_r(LGW_DBG_ARB_MCU_RAM_DATA, &read_val); + fw_version = (uint8_t)read_val; + if (fw_version != FW_VERSION_ARB) { +- DEBUG_PRINTF("ERROR: Version of arbiter firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_ARB); ++ ERROR_PRINTF("Version of arbiter firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_ARB); + return LGW_HAL_ERROR; + } + +@@ -1010,7 +1036,7 @@ int lgw_start(void) { + + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != 0x10) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + +@@ -1023,7 +1049,7 @@ int lgw_start(void) { + wait_ms(1); + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != (0x30 + i)) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + } +@@ -1036,7 +1062,7 @@ int lgw_start(void) { + wait_ms(1); + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != 0x30) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + } +@@ -1048,7 +1074,7 @@ int lgw_start(void) { + wait_ms(1); + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != 0x33) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + +@@ -1059,7 +1085,7 @@ int lgw_start(void) { + wait_ms(1); + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != 0x30) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + +@@ -1071,7 +1097,7 @@ int lgw_start(void) { + DEBUG_MSG("Info: putting back original RADIO_SELECT value\n"); + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != 0x40) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + +@@ -1080,7 +1106,7 @@ int lgw_start(void) { + + /* */ + if (lbt_is_enabled() == true) { +- printf("INFO: Configuring LBT, this may take few seconds, please wait...\n"); ++ INFO_PRINTF("Configuring LBT, this may take few seconds, please wait...\n"); + wait_ms(8400); + } + +@@ -1114,13 +1140,13 @@ int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { + + /* check if the concentrator is running */ + if (lgw_is_started == false) { +- DEBUG_MSG("ERROR: CONCENTRATOR IS NOT RUNNING, START IT BEFORE RECEIVING\n"); ++ ERROR_PRINTF("CONCENTRATOR IS NOT RUNNING, START IT BEFORE RECEIVING\n"); + return LGW_HAL_ERROR; + } + + /* check input variables */ + if ((max_pkt <= 0) || (max_pkt > LGW_PKT_FIFO_SIZE)) { +- DEBUG_PRINTF("ERROR: %d = INVALID MAX NUMBER OF PACKETS TO FETCH\n", max_pkt); ++ ERROR_PRINTF("%d = INVALID MAX NUMBER OF PACKETS TO FETCH\n", max_pkt); + return LGW_HAL_ERROR; + } + CHECK_NULL(pkt_data); +@@ -1247,7 +1273,7 @@ int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { + bw_pow = 4; + break; + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", p->bandwidth); ++ ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", p->bandwidth); + delay_x = 0; + bw_pow = 0; + } +@@ -1304,7 +1330,7 @@ int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { + /* RSSI correction */ + p->rssi = RSSI_FSK_POLY_0 + RSSI_FSK_POLY_1 * p->rssi + RSSI_FSK_POLY_2 * pow(p->rssi, 2); + } else { +- DEBUG_MSG("ERROR: UNEXPECTED PACKET ORIGIN\n"); ++ ERROR_PRINTF("UNEXPECTED PACKET ORIGIN\n"); + p->status = STAT_UNDEFINED; + p->modulation = MOD_UNDEFINED; + p->rssi = -128.0; +@@ -1347,61 +1373,61 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { + + /* check if the concentrator is running */ + if (lgw_is_started == false) { +- DEBUG_MSG("ERROR: CONCENTRATOR IS NOT RUNNING, START IT BEFORE SENDING\n"); ++ ERROR_PRINTF("CONCENTRATOR IS NOT RUNNING, START IT BEFORE SENDING\n"); + return LGW_HAL_ERROR; + } + + /* check input range (segfault prevention) */ + if (pkt_data.rf_chain >= LGW_RF_CHAIN_NB) { +- DEBUG_MSG("ERROR: INVALID RF_CHAIN TO SEND PACKETS\n"); ++ ERROR_PRINTF("INVALID RF_CHAIN TO SEND PACKETS\n"); + return LGW_HAL_ERROR; + } + + /* check input variables */ + if (rf_tx_enable[pkt_data.rf_chain] == false) { +- DEBUG_MSG("ERROR: SELECTED RF_CHAIN IS DISABLED FOR TX ON SELECTED BOARD\n"); ++ ERROR_PRINTF("SELECTED RF_CHAIN IS DISABLED FOR TX ON SELECTED BOARD\n"); + return LGW_HAL_ERROR; + } + if (rf_enable[pkt_data.rf_chain] == false) { +- DEBUG_MSG("ERROR: SELECTED RF_CHAIN IS DISABLED\n"); ++ ERROR_PRINTF("SELECTED RF_CHAIN IS DISABLED\n"); + return LGW_HAL_ERROR; + } + if (!IS_TX_MODE(pkt_data.tx_mode)) { +- DEBUG_MSG("ERROR: TX_MODE NOT SUPPORTED\n"); ++ ERROR_PRINTF("TX_MODE NOT SUPPORTED\n"); + return LGW_HAL_ERROR; + } + if (pkt_data.modulation == MOD_LORA) { + if (!IS_LORA_BW(pkt_data.bandwidth)) { +- DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA TX\n"); ++ ERROR_PRINTF("BANDWIDTH NOT SUPPORTED BY LORA TX\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_STD_DR(pkt_data.datarate)) { +- DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY LORA TX\n"); ++ ERROR_PRINTF("DATARATE NOT SUPPORTED BY LORA TX\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_CR(pkt_data.coderate)) { +- DEBUG_MSG("ERROR: CODERATE NOT SUPPORTED BY LORA TX\n"); ++ ERROR_PRINTF("CODERATE NOT SUPPORTED BY LORA TX\n"); + return LGW_HAL_ERROR; + } + if (pkt_data.size > 255) { +- DEBUG_MSG("ERROR: PAYLOAD LENGTH TOO BIG FOR LORA TX\n"); ++ ERROR_PRINTF("PAYLOAD LENGTH TOO BIG FOR LORA TX\n"); + return LGW_HAL_ERROR; + } + } else if (pkt_data.modulation == MOD_FSK) { + if((pkt_data.f_dev < 1) || (pkt_data.f_dev > 200)) { +- DEBUG_MSG("ERROR: TX FREQUENCY DEVIATION OUT OF ACCEPTABLE RANGE\n"); ++ ERROR_PRINTF("TX FREQUENCY DEVIATION OUT OF ACCEPTABLE RANGE\n"); + return LGW_HAL_ERROR; + } + if(!IS_FSK_DR(pkt_data.datarate)) { +- DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); ++ ERROR_PRINTF("DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); + return LGW_HAL_ERROR; + } + if (pkt_data.size > 255) { +- DEBUG_MSG("ERROR: PAYLOAD LENGTH TOO BIG FOR FSK TX\n"); ++ ERROR_PRINTF("PAYLOAD LENGTH TOO BIG FOR FSK TX\n"); + return LGW_HAL_ERROR; + } + } else { +- DEBUG_MSG("ERROR: INVALID TX MODULATION\n"); ++ ERROR_PRINTF("INVALID TX MODULATION\n"); + return LGW_HAL_ERROR; + } + +@@ -1448,10 +1474,15 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { + part_frac = ((pkt_data.freq_hz % (SX125x_32MHz_FRAC << 8)) << 8) / SX125x_32MHz_FRAC; /* fractional part, gives middle part and LSB */ + break; + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type[0]); ++ ERROR_PRINTF("UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type[0]); break; } - + + if( lgwx_device_mode ) { -+ pkt_data.invert_pol = false; -+ pkt_data.no_crc = false; ++ pkt_data.invert_pol = false; ++ pkt_data.no_crc = false; + } + buff[0] = 0xFF & part_int; /* Most Significant Byte */ buff[1] = 0xFF & (part_frac >> 8); /* middle byte */ buff[2] = 0xFF & part_frac; /* Least Significant Byte */ -@@ -1600,10 +1627,17 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { +@@ -1482,14 +1513,14 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { + case DR_LORA_SF10: buff[9] = 10; break; + case DR_LORA_SF11: buff[9] = 11; break; + case DR_LORA_SF12: buff[9] = 12; break; +- default: DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.datarate); ++ default: ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.datarate); + } + switch (pkt_data.coderate) { + case CR_LORA_4_5: buff[9] |= 1 << 4; break; + case CR_LORA_4_6: buff[9] |= 2 << 4; break; + case CR_LORA_4_7: buff[9] |= 3 << 4; break; + case CR_LORA_4_8: buff[9] |= 4 << 4; break; +- default: DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.coderate); ++ default: ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.coderate); + } + if (pkt_data.no_crc == false) { + buff[9] |= 0x80; /* set 'CRC enable' bit */ +@@ -1505,7 +1536,7 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { + case BW_125KHZ: buff[11] = 0; break; + case BW_250KHZ: buff[11] = 1; break; + case BW_500KHZ: buff[11] = 2; break; +- default: DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.bandwidth); ++ default: ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.bandwidth); + } + if (pkt_data.no_header == true) { + buff[11] |= 0x04; /* set 'implicit header' bit */ +@@ -1582,7 +1613,7 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { + buff[0] &= 0x7F; /* Always use narrow band for FSK (force MSB to 0) */ + + } else { +- DEBUG_MSG("ERROR: INVALID TX MODULATION..\n"); ++ ERROR_PRINTF("INVALID TX MODULATION..\n"); + return LGW_HAL_ERROR; + } + +@@ -1600,10 +1631,17 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { lgw_reg_wb(LGW_TX_DATA_BUF_DATA, buff, transfer_size); DEBUG_ARRAY(i, transfer_size, buff); - + - x = lbt_is_channel_free(&pkt_data, tx_start_delay, &tx_allowed); - if (x != LGW_LBT_SUCCESS) { - DEBUG_MSG("ERROR: Failed to check channel availability for TX\n"); - return LGW_HAL_ERROR; + if( lgwx_lbt_mode == LGWX_LBT_MODE_OFF ) { -+ tx_allowed = true; ++ tx_allowed = true; + } else { -+ //XXX:TBD: if( lgwx_lbt_mode == LGWX_LBT_MODE_EU868 ) { -+ //XXX:TBD: // change txend time so that lbt_is_channel_free checks if dead gap is within 5ms (PSA rules) -+ //XXX:TBD: } -+ x = lbt_is_channel_free(&pkt_data, tx_start_delay, &tx_allowed); -+ if (x != LGW_LBT_SUCCESS) { -+ DEBUG_MSG("ERROR: Failed to check channel availability for TX\n"); -+ return LGW_HAL_ERROR; -+ } ++ //XXX:TBD: if( lgwx_lbt_mode == LGWX_LBT_MODE_EU868 ) { ++ //XXX:TBD: // change txend time so that lbt_is_channel_free checks if dead gap is within 5ms (PSA rules) ++ //XXX:TBD: } ++ x = lbt_is_channel_free(&pkt_data, tx_start_delay, &tx_allowed); ++ if (x != LGW_LBT_SUCCESS) { ++ ERROR_PRINTF("Failed to check channel availability for TX\n"); ++ return LGW_HAL_ERROR; ++ } } if (tx_allowed == true) { switch(pkt_data.tx_mode) { +@@ -1620,11 +1658,11 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { + break; + + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.tx_mode); ++ ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.tx_mode); + return LGW_HAL_ERROR; + } + } else { +- DEBUG_MSG("ERROR: Cannot send packet, channel is busy (LBT)\n"); ++ ERROR_PRINTF("Cannot send packet, channel is busy (LBT)\n"); + return LGW_LBT_ISSUE; + } + +@@ -1657,7 +1695,7 @@ int lgw_status(uint8_t select, uint8_t *code) { + return LGW_HAL_SUCCESS; + + } else { +- DEBUG_MSG("ERROR: SELECTION INVALID, NO STATUS TO RETURN\n"); ++ ERROR_PRINTF("SELECTION INVALID, NO STATUS TO RETURN\n"); + return LGW_HAL_ERROR; + } + +@@ -1705,7 +1743,7 @@ uint32_t lgw_time_on_air(struct lgw_pkt_tx_s *packet) { + double Tsym, Tpreamble, Tpayload, Tfsk; + + if (packet == NULL) { +- DEBUG_MSG("ERROR: Failed to compute time on air, wrong parameter\n"); ++ ERROR_PRINTF("Failed to compute time on air, wrong parameter\n"); + return 0; + } + +@@ -1715,7 +1753,7 @@ uint32_t lgw_time_on_air(struct lgw_pkt_tx_s *packet) { + if (val != -1) { + BW = (uint16_t)(val / 1E3); + } else { +- DEBUG_PRINTF("ERROR: Cannot compute time on air for this packet, unsupported bandwidth (0x%02X)\n", packet->bandwidth); ++ ERROR_PRINTF("Cannot compute time on air for this packet, unsupported bandwidth (0x%02X)\n", packet->bandwidth); + return 0; + } + +@@ -1724,7 +1762,7 @@ uint32_t lgw_time_on_air(struct lgw_pkt_tx_s *packet) { + if (val != -1) { + SF = (uint8_t)val; + } else { +- DEBUG_PRINTF("ERROR: Cannot compute time on air for this packet, unsupported datarate (0x%02X)\n", packet->datarate); ++ ERROR_PRINTF("Cannot compute time on air for this packet, unsupported datarate (0x%02X)\n", packet->datarate); + return 0; + } + +@@ -1758,7 +1796,7 @@ uint32_t lgw_time_on_air(struct lgw_pkt_tx_s *packet) { + Tpacket = (uint32_t)Tfsk + 1; /* add margin for rounding */ + } else { + Tpacket = 0; +- DEBUG_PRINTF("ERROR: Cannot compute time on air for this packet, unsupported modulation (0x%02X)\n", packet->modulation); ++ ERROR_PRINTF("Cannot compute time on air for this packet, unsupported modulation (0x%02X)\n", packet->modulation); + } + + return Tpacket; +diff --git a/libloragw/src/loragw_lbt.c b/libloragw/src/loragw_lbt.c +index 9c43521..515e9ac 100644 +--- a/libloragw/src/loragw_lbt.c ++++ b/libloragw/src/loragw_lbt.c +@@ -41,6 +41,8 @@ Maintainer: Michael Coracin + #define CHECK_NULL(a) if(a==NULL){return LGW_REG_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + #define LBT_TIMESTAMP_MASK 0x007FF000 /* 11-bits timestamp */ + + /* -------------------------------------------------------------------------- */ +@@ -326,7 +328,7 @@ int lbt_is_channel_free(struct lgw_pkt_tx_s * pkt_data, uint16_t tx_start_delay, + delta_time = tx_end_time - lbt_time; + } else { + /* It means LBT counter has wrapped */ +- printf("LBT: lbt counter has wrapped\n"); ++ DEBUG_PRINTF("LBT: lbt counter has wrapped\n"); + delta_time = (LBT_TIMESTAMP_MASK - lbt_time) + tx_end_time; + } + +diff --git a/libloragw/src/loragw_radio.c b/libloragw/src/loragw_radio.c +index b3046a9..a01f65b 100644 +--- a/libloragw/src/loragw_radio.c ++++ b/libloragw/src/loragw_radio.c +@@ -46,6 +46,8 @@ Maintainer: Michael Coracin + #define CHECK_NULL(a) if(a==NULL){return LGW_REG_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE TYPES -------------------------------------------------------- */ + +diff --git a/libloragw/src/loragw_reg.c b/libloragw/src/loragw_reg.c +index 14e23cd..6d8aab3 100644 +--- a/libloragw/src/loragw_reg.c ++++ b/libloragw/src/loragw_reg.c +@@ -42,6 +42,8 @@ Maintainer: Sylvain Miermont + #define CHECK_NULL(a) if(a==NULL){return LGW_REG_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + diff --git a/libloragw/src/loragw_spi.native.c b/libloragw/src/loragw_spi.native.c -index c01ed1c..0e2b64c 100644 +index c01ed1c..7cc7eea 100644 --- a/libloragw/src/loragw_spi.native.c +++ b/libloragw/src/loragw_spi.native.c -@@ -54,7 +54,7 @@ Maintainer: Sylvain Miermont +@@ -48,13 +48,15 @@ Maintainer: Sylvain Miermont + #define CHECK_NULL(a) if(a==NULL){return LGW_SPI_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + #define READ_ACCESS 0x00 #define WRITE_ACCESS 0x80 - #define SPI_SPEED 8000000 +-#define SPI_SPEED 8000000 -#define SPI_DEV_PATH "/dev/spidev0.0" ++#define SPI_SPEED (getenv("LORAGW_SPI_SPEED")==NULL ? 8000000 : atoi(getenv("LORAGW_SPI_SPEED"))) +#define SPI_DEV_PATH (getenv("LORAGW_SPI")==NULL ? "/dev/spidev0.0" : getenv("LORAGW_SPI")) //#define SPI_DEV_PATH "/dev/spidev32766.0" - + /* -------------------------------------------------------------------------- */ +@@ -96,6 +98,7 @@ int lgw_spi_open(void **spi_target_ptr) { + } + + /* setting SPI max clk (in Hz) */ ++ INFO_PRINTF("Setting SPI speed to %u\n", SPI_SPEED); + i = SPI_SPEED; + a = ioctl(dev, SPI_IOC_WR_MAX_SPEED_HZ, &i); + b = ioctl(dev, SPI_IOC_RD_MAX_SPEED_HZ, &i); +@@ -111,7 +114,7 @@ int lgw_spi_open(void **spi_target_ptr) { + 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"); ++ ERROR_PRINTF("SPI PORT FAIL TO SET MSB FIRST\n"); + close(dev); + free(spi_device); + return LGW_SPI_ERROR; +@@ -122,14 +125,14 @@ int lgw_spi_open(void **spi_target_ptr) { + 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"); ++ ERROR_PRINTF("SPI PORT FAIL TO SET 8 BITS-PER-WORD\n"); + close(dev); + return LGW_SPI_ERROR; + } + + *spi_device = dev; + *spi_target_ptr = (void *)spi_device; +- DEBUG_MSG("Note: SPI port opened and configured ok\n"); ++ INFO_PRINTF("Note: SPI port opened and configured ok\n"); + return LGW_SPI_SUCCESS; + } + +@@ -150,10 +153,10 @@ int lgw_spi_close(void *spi_target) { + + /* determine return code */ + if (a < 0) { +- DEBUG_MSG("ERROR: SPI PORT FAILED TO CLOSE\n"); ++ ERROR_PRINTF("SPI PORT FAILED TO CLOSE\n"); + return LGW_SPI_ERROR; + } else { +- DEBUG_MSG("Note: SPI port closed\n"); ++ INFO_PRINTF("Note: SPI port closed\n"); + return LGW_SPI_SUCCESS; + } + } +@@ -199,7 +202,7 @@ int lgw_spi_w(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, ui + + /* determine return code */ + if (a != (int)k.len) { +- DEBUG_MSG("ERROR: SPI WRITE FAILURE\n"); ++ ERROR_PRINTF("SPI WRITE FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI write success\n"); +@@ -249,7 +252,7 @@ int lgw_spi_r(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, ui + + /* determine return code */ + if (a != (int)k.len) { +- DEBUG_MSG("ERROR: SPI READ FAILURE\n"); ++ ERROR_PRINTF("SPI READ FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI read success\n"); +@@ -277,7 +280,7 @@ int lgw_spi_wb(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, u + } + CHECK_NULL(data); + if (size == 0) { +- DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); ++ ERROR_PRINTF("BURST OF NULL LENGTH\n"); + return LGW_SPI_ERROR; + } + +@@ -312,7 +315,7 @@ int lgw_spi_wb(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, u + + /* determine return code */ + if (byte_transfered != size) { +- DEBUG_MSG("ERROR: SPI BURST WRITE FAILURE\n"); ++ ERROR_PRINTF("SPI BURST WRITE FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI burst write success\n"); +@@ -339,7 +342,7 @@ int lgw_spi_rb(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, u + } + CHECK_NULL(data); + if (size == 0) { +- DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); ++ ERROR_PRINTF("ERROR: BURST OF NULL LENGTH\n"); + return LGW_SPI_ERROR; + } + +@@ -368,16 +371,16 @@ int lgw_spi_rb(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, u + k[1].rx_buf = (unsigned long)(data + offset); + k[1].len = chunk_size; + byte_transfered += (ioctl(spi_device, SPI_IOC_MESSAGE(2), &k) - k[0].len ); +- DEBUG_PRINTF("BURST READ: to trans %d # chunk %d # transferred %d \n", size_to_do, chunk_size, byte_transfered); ++ // 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"); ++ ERROR_PRINTF("ERROR: SPI BURST READ FAILURE\n"); + return LGW_SPI_ERROR; + } else { +- DEBUG_MSG("Note: SPI burst read success\n"); ++ // DEBUG_MSG("Note: SPI burst read success\n"); + return LGW_SPI_SUCCESS; + } + } diff --git a/deps/lgw/v5.0.1-linux.patch b/deps/lgw/v5.0.1-linux.patch index 8a2281b..3c1aaf6 100644 --- a/deps/lgw/v5.0.1-linux.patch +++ b/deps/lgw/v5.0.1-linux.patch @@ -1,15 +1,20 @@ diff --git a/libloragw/Makefile b/libloragw/Makefile -index 53c33d9..a8a09a2 100644 +index 53c33d9..cc7d016 100644 --- a/libloragw/Makefile +++ b/libloragw/Makefile -@@ -7,6 +7,7 @@ include library.cfg - +@@ -7,10 +7,12 @@ include library.cfg + ARCH ?= CROSS_COMPILE ?= + CC := $(CROSS_COMPILE)gcc AR := $(CROSS_COMPILE)ar - + + CFLAGS := -O2 -Wall -Wextra -std=c99 -Iinc -I. ++CFLAGS += ${EXTRA_CFLAGS} + + OBJDIR = obj + INCLUDES = $(wildcard inc/*.h) diff --git a/libloragw/inc/loragw_hal.h b/libloragw/inc/loragw_hal.h index d5f9ade..57927c4 100644 --- a/libloragw/inc/loragw_hal.h @@ -17,7 +22,7 @@ index d5f9ade..57927c4 100644 @@ -414,6 +414,12 @@ const char* lgw_version_info(void); */ uint32_t lgw_time_on_air(struct lgw_pkt_tx_s *packet); - + +extern uint8_t lgwx_device_mode; +extern uint8_t lgwx_beacon_len; +extern uint8_t lgwx_beacon_sf; @@ -25,109 +30,1070 @@ index d5f9ade..57927c4 100644 +enum { LGWX_LBT_MODE_DFLT=0, LGWX_LBT_MODE_OFF = 1 }; + #endif - + /* --- EOF ------------------------------------------------------------------ */ +diff --git a/libloragw/inc/loragw_stationlog.h b/libloragw/inc/loragw_stationlog.h +new file mode 100644 +index 0000000..a282b8f +--- /dev/null ++++ b/libloragw/inc/loragw_stationlog.h +@@ -0,0 +1,26 @@ ++#ifndef _LORAGW_STATIONLOG_H ++#define _LORAGW_STATIONLOG_H ++ ++#if defined(STATIONLOG) ++ ++#undef DEBUG_PRINTF ++#undef DEBUG_MSG ++ ++enum { XDEBUG=0, DEBUG, VERBOSE, INFO, NOTICE, WARNING, ERROR, CRITICAL }; ++extern void log_hal (uint8_t level, const char* fmt, ...); ++#define ERROR_PRINTF(fmt, ...) log_hal(ERROR , "[%s:%d] "fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__) ++#define INFO_PRINTF(fmt, ...) log_hal(INFO , "[%s:%d] "fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__) ++#define DEBUG_PRINTF(fmt, ...) log_hal(XDEBUG , "[%s:%d] "fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__) ++#define DEBUG_MSG(str) log_hal(XDEBUG , "[%s:%d] %s", __FUNCTION__, __LINE__, str) ++#define XDEBUG_PRINTF(fmt, ...) log_hal(XDEBUG , "[%s:%d] "fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__) ++#define XDEBUG_MSG(str) log_hal(XDEBUG , "[%s:%d] %s", __FUNCTION__, __LINE__, str) ++ ++#else // !defined(STATIONLOG) ++ ++#define ERROR_PRINTF(fmt, ...) DEBUG_PRINTF(fmt, ## __VA_ARGS__) ++#define INFO_PRINTF(fmt, ...) DEBUG_PRINTF(fmt, ## __VA_ARGS__) ++#define XDEBUG_PRINTF(fmt, ...) DEBUG_PRINTF(fmt, ## __VA_ARGS__) ++#define XDEBUG_MSG(str) DEBUG_MSG(str) ++#endif ++ ++#endif +diff --git a/libloragw/src/loragw_fpga.c b/libloragw/src/loragw_fpga.c +index 465f43e..9b98786 100644 +--- a/libloragw/src/loragw_fpga.c ++++ b/libloragw/src/loragw_fpga.c +@@ -43,6 +43,8 @@ Maintainer: Michael Coracin + #define CHECK_NULL(a) if(a==NULL){return LGW_REG_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + +@@ -140,21 +142,16 @@ int lgw_fpga_configure(uint32_t tx_notch_freq) { + } + + /* Get supported FPGA features */ +- printf("INFO: FPGA supported features:"); + lgw_fpga_reg_r(LGW_FPGA_FEATURE, &val); + tx_notch_support = TAKE_N_BITS_FROM((uint8_t)val, 0, 1); +- if (tx_notch_support == true) { +- printf(" [TX filter] "); +- } + spectral_scan_support = TAKE_N_BITS_FROM((uint8_t)val, 1, 1); +- if (spectral_scan_support == true) { +- printf(" [Spectral Scan] "); +- } + lbt_support = TAKE_N_BITS_FROM((uint8_t)val, 2, 1); +- if (lbt_support == true) { +- printf(" [LBT] "); +- } +- printf("\n"); ++ ++ INFO_PRINTF("INFO: FPGA supported features: %s%s%s", ++ tx_notch_support ? " [TX filter] " : "", ++ spectral_scan_support ? " [Spectral Scan] " : "", ++ lbt_support ? " [lbt_support] " : "" ++ ); + + x = lgw_fpga_reg_w(LGW_FPGA_CTRL_INPUT_SYNC_I, 1); + x |= lgw_fpga_reg_w(LGW_FPGA_CTRL_INPUT_SYNC_Q, 1); +diff --git a/libloragw/src/loragw_gps.c b/libloragw/src/loragw_gps.c +index c0e0ded..14eff6e 100644 +--- a/libloragw/src/loragw_gps.c ++++ b/libloragw/src/loragw_gps.c +@@ -39,16 +39,20 @@ Maintainer: Michael Coracin + + #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + #if DEBUG_GPS == 1 +- #define DEBUG_MSG(args...) fprintf(stderr, args) ++ #define DEBUG_MSG(str) fprintf(stderr, str) ++ #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args) + #define DEBUG_ARRAY(a,b,c) for(a=0;a %H", buff_size, serial_buff); ++#else + DEBUG_MSG("Note: parsing UBX frame> "); + for (i=0; i= LGW_RF_CHAIN_NB) { +- DEBUG_MSG("ERROR: NOT A VALID RF_CHAIN NUMBER\n"); ++ ERROR_PRINTF("NOT A VALID RF_CHAIN NUMBER\n"); + return LGW_HAL_ERROR; + } + + /* check if radio type is supported */ + if ((conf.type != LGW_RADIO_TYPE_SX1255) && (conf.type != LGW_RADIO_TYPE_SX1257)) { +- DEBUG_MSG("ERROR: NOT A VALID RADIO TYPE\n"); ++ ERROR_PRINTF("NOT A VALID RADIO TYPE\n"); + return LGW_HAL_ERROR; + } + +@@ -498,13 +524,13 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + + /* check if the concentrator is running */ + if (lgw_is_started == true) { +- DEBUG_MSG("ERROR: CONCENTRATOR IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); ++ ERROR_PRINTF("CONCENTRATOR IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); + return LGW_HAL_ERROR; + } + + /* check input range (segfault prevention) */ + if (if_chain >= LGW_IF_CHAIN_NB) { +- DEBUG_PRINTF("ERROR: %d NOT A VALID IF_CHAIN NUMBER\n", if_chain); ++ ERROR_PRINTF("%d NOT A VALID IF_CHAIN NUMBER\n", if_chain); + return LGW_HAL_ERROR; + } + +@@ -518,10 +544,10 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + + /* check 'general' parameters */ + if (ifmod_config[if_chain] == IF_UNDEFINED) { +- DEBUG_PRINTF("ERROR: IF CHAIN %d NOT CONFIGURABLE\n", if_chain); ++ ERROR_PRINTF("IF CHAIN %d NOT CONFIGURABLE\n", if_chain); + } + if (conf.rf_chain >= LGW_RF_CHAIN_NB) { +- DEBUG_MSG("ERROR: INVALID RF_CHAIN TO ASSOCIATE WITH A LORA_STD IF CHAIN\n"); ++ ERROR_PRINTF("INVALID RF_CHAIN TO ASSOCIATE WITH A LORA_STD IF CHAIN\n"); + return LGW_HAL_ERROR; + } + /* check if IF frequency is optimal based on channel and radio bandwidths */ +@@ -539,10 +565,10 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + } + bw_hz = lgw_bw_getval(conf.bandwidth); /* channel bandwidth */ + if ((conf.freq_hz + ((bw_hz==-1)?LGW_REF_BW:bw_hz)/2) > ((int32_t)rf_rx_bandwidth/2)) { +- DEBUG_PRINTF("ERROR: IF FREQUENCY %d TOO HIGH\n", conf.freq_hz); ++ ERROR_PRINTF("IF FREQUENCY %d TOO HIGH\n", conf.freq_hz); + return LGW_HAL_ERROR; + } else if ((conf.freq_hz - ((bw_hz==-1)?LGW_REF_BW:bw_hz)/2) < -((int32_t)rf_rx_bandwidth/2)) { +- DEBUG_PRINTF("ERROR: IF FREQUENCY %d TOO LOW\n", conf.freq_hz); ++ ERROR_PRINTF("IF FREQUENCY %d TOO LOW\n", conf.freq_hz); + return LGW_HAL_ERROR; + } + +@@ -559,11 +585,11 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + } + /* check BW & DR */ + if (!IS_LORA_BW(conf.bandwidth)) { +- DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA_STD IF CHAIN\n"); ++ ERROR_PRINTF("BANDWIDTH NOT SUPPORTED BY LORA_STD IF CHAIN\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_STD_DR(conf.datarate)) { +- DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY LORA_STD IF CHAIN\n"); ++ ERROR_PRINTF("DATARATE NOT SUPPORTED BY LORA_STD IF CHAIN\n"); + return LGW_HAL_ERROR; + } + /* set internal configuration */ +@@ -591,11 +617,11 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + } + /* check BW & DR */ + if (conf.bandwidth != BW_125KHZ) { +- DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); ++ ERROR_PRINTF("BANDWIDTH NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_MULTI_DR(conf.datarate)) { +- DEBUG_MSG("ERROR: DATARATE(S) NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); ++ ERROR_PRINTF("DATARATE(S) NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); + return LGW_HAL_ERROR; + } + /* set internal configuration */ +@@ -617,11 +643,11 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + } + /* check BW & DR */ + if(!IS_FSK_BW(conf.bandwidth)) { +- DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY FSK IF CHAIN\n"); ++ ERROR_PRINTF("BANDWIDTH NOT SUPPORTED BY FSK IF CHAIN\n"); + return LGW_HAL_ERROR; + } + if(!IS_FSK_DR(conf.datarate)) { +- DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); ++ ERROR_PRINTF("DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); + return LGW_HAL_ERROR; + } + /* set internal configuration */ +@@ -638,7 +664,7 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + break; + + default: +- DEBUG_PRINTF("ERROR: IF CHAIN %d TYPE NOT SUPPORTED\n", if_chain); ++ ERROR_PRINTF("IF CHAIN %d TYPE NOT SUPPORTED\n", if_chain); + return LGW_HAL_ERROR; + } + +@@ -652,7 +678,7 @@ int lgw_txgain_setconf(struct lgw_tx_gain_lut_s *conf) { + + /* Check LUT size */ + if ((conf->size < 1) || (conf->size > TX_GAIN_LUT_SIZE_MAX)) { +- DEBUG_PRINTF("ERROR: TX gain LUT must have at least one entry and maximum %d entries\n", TX_GAIN_LUT_SIZE_MAX); ++ ERROR_PRINTF("TX gain LUT must have at least one entry and maximum %d entries\n", TX_GAIN_LUT_SIZE_MAX); + return LGW_HAL_ERROR; + } + +@@ -661,22 +687,22 @@ int lgw_txgain_setconf(struct lgw_tx_gain_lut_s *conf) { + for (i = 0; i < txgain_lut.size; i++) { + /* Check gain range */ + if (conf->lut[i].dig_gain > 3) { +- DEBUG_MSG("ERROR: TX gain LUT: SX1301 digital gain must be between 0 and 3\n"); ++ ERROR_PRINTF("TX gain LUT: SX1301 digital gain must be between 0 and 3\n"); + return LGW_HAL_ERROR; + } + if (conf->lut[i].dac_gain != 3) { +- DEBUG_MSG("ERROR: TX gain LUT: SX1257 DAC gains != 3 are not supported\n"); ++ ERROR_PRINTF("TX gain LUT: SX1257 DAC gains != 3 are not supported\n"); + return LGW_HAL_ERROR; + } + if (conf->lut[i].mix_gain > 15) { +- DEBUG_MSG("ERROR: TX gain LUT: SX1257 mixer gain must not exceed 15\n"); ++ ERROR_PRINTF("TX gain LUT: SX1257 mixer gain must not exceed 15\n"); + return LGW_HAL_ERROR; + } else if (conf->lut[i].mix_gain < 8) { +- DEBUG_MSG("ERROR: TX gain LUT: SX1257 mixer gains < 8 are not supported\n"); ++ ERROR_PRINTF("TX gain LUT: SX1257 mixer gains < 8 are not supported\n"); + return LGW_HAL_ERROR; + } + if (conf->lut[i].pa_gain > 3) { +- DEBUG_MSG("ERROR: TX gain LUT: External PA gain must not exceed 3\n"); ++ ERROR_PRINTF("TX gain LUT: External PA gain must not exceed 3\n"); + return LGW_HAL_ERROR; + } + +@@ -713,7 +739,7 @@ int lgw_start(void) { + + reg_stat = lgw_connect(false, rf_tx_notch_freq[rf_tx_enable[1]?1:0]); + if (reg_stat == LGW_REG_ERROR) { +- DEBUG_MSG("ERROR: FAIL TO CONNECT BOARD\n"); ++ ERROR_PRINTF("FAIL TO CONNECT BOARD\n"); + return LGW_HAL_ERROR; + } + +@@ -735,12 +761,12 @@ int lgw_start(void) { + /* setup the radios */ + err = lgw_setup_sx125x(0, rf_clkout, rf_enable[0], rf_radio_type[0], rf_rx_freq[0]); + if (err != 0) { +- DEBUG_MSG("ERROR: Failed to setup sx125x radio for RF chain 0\n"); ++ ERROR_PRINTF("Failed to setup sx125x radio for RF chain 0\n"); + return LGW_HAL_ERROR; + } + err = lgw_setup_sx125x(1, rf_clkout, rf_enable[1], rf_radio_type[1], rf_rx_freq[1]); + if (err != 0) { +- DEBUG_MSG("ERROR: Failed to setup sx125x radio for RF chain 0\n"); ++ ERROR_PRINTF("Failed to setup sx125x radio for RF chain 0\n"); + return LGW_HAL_ERROR; + } + +@@ -753,7 +779,7 @@ int lgw_start(void) { + lgw_reg_w(LGW_CLK32M_EN, 1); + i = lbt_setup(); + if (i != LGW_LBT_SUCCESS) { +- DEBUG_MSG("ERROR: lbt_setup() did not return SUCCESS\n"); ++ ERROR_PRINTF("lbt_setup() did not return SUCCESS\n"); + return LGW_HAL_ERROR; + } + +@@ -761,7 +787,7 @@ int lgw_start(void) { + lgw_reg_w(LGW_CLK32M_EN, 0); + i = lbt_start(); + if (i != LGW_LBT_SUCCESS) { +- DEBUG_MSG("ERROR: lbt_start() did not return SUCCESS\n"); ++ ERROR_PRINTF("lbt_start() did not return SUCCESS\n"); + return LGW_HAL_ERROR; + } + } +@@ -794,7 +820,7 @@ int lgw_start(void) { + cal_cmd |= 0x00; /* Bit 5: 0: SX1257, 1: SX1255 */ + break; + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type[0]); ++ ERROR_PRINTF("UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type[0]); + break; + } + +@@ -812,7 +838,7 @@ int lgw_start(void) { + lgw_reg_r(LGW_DBG_AGC_MCU_RAM_DATA, &read_val); + fw_version = (uint8_t)read_val; + if (fw_version != FW_VERSION_CAL) { +- printf("ERROR: Version of calibration firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_CAL); ++ ERROR_PRINTF("Version of calibration firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_CAL); + return -1; + } + +@@ -838,7 +864,7 @@ int lgw_start(void) { + bit 6: radio B TX DC Offset correction successful + */ + if ((cal_status & 0x81) != 0x81) { +- DEBUG_PRINTF("ERROR: CALIBRATION FAILURE (STATUS = %u)\n", cal_status); ++ ERROR_PRINTF("CALIBRATION FAILURE (STATUS = %u)\n", cal_status); + return LGW_HAL_ERROR; + } else { + DEBUG_PRINTF("Note: calibration finished (status = %u)\n", cal_status); +@@ -883,7 +909,7 @@ int lgw_start(void) { + + /* Sanity check for RX frequency */ + if (rf_rx_freq[0] == 0) { +- DEBUG_MSG("ERROR: wrong configuration, rf_rx_freq[0] is not set\n"); ++ ERROR_PRINTF("wrong configuration, rf_rx_freq[0] is not set\n"); + return LGW_HAL_ERROR; + } + +@@ -939,7 +965,7 @@ int lgw_start(void) { + case BW_250KHZ: lgw_reg_w(LGW_MBWSSF_MODEM_BW, 1); break; + case BW_500KHZ: lgw_reg_w(LGW_MBWSSF_MODEM_BW, 2); break; + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", lora_rx_bw); ++ ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", lora_rx_bw); + return LGW_HAL_ERROR; + } + switch(lora_rx_sf) { +@@ -950,7 +976,7 @@ int lgw_start(void) { + case DR_LORA_SF11: lgw_reg_w(LGW_MBWSSF_RATE_SF, 11); break; + case DR_LORA_SF12: lgw_reg_w(LGW_MBWSSF_RATE_SF, 12); break; + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", lora_rx_sf); ++ ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", lora_rx_sf); + return LGW_HAL_ERROR; + } + lgw_reg_w(LGW_MBWSSF_PPM_OFFSET, lora_rx_ppm_offset); /* default 0 */ +@@ -994,14 +1020,14 @@ int lgw_start(void) { + lgw_reg_r(LGW_DBG_AGC_MCU_RAM_DATA, &read_val); + fw_version = (uint8_t)read_val; + if (fw_version != FW_VERSION_AGC) { +- DEBUG_PRINTF("ERROR: Version of AGC firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_AGC); ++ ERROR_PRINTF("Version of AGC firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_AGC); + return LGW_HAL_ERROR; + } + lgw_reg_w(LGW_DBG_ARB_MCU_RAM_ADDR, FW_VERSION_ADDR); + lgw_reg_r(LGW_DBG_ARB_MCU_RAM_DATA, &read_val); + fw_version = (uint8_t)read_val; + if (fw_version != FW_VERSION_ARB) { +- DEBUG_PRINTF("ERROR: Version of arbiter firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_ARB); ++ ERROR_PRINTF("Version of arbiter firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_ARB); + return LGW_HAL_ERROR; + } + +@@ -1010,7 +1036,7 @@ int lgw_start(void) { + + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != 0x10) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + +@@ -1023,7 +1049,7 @@ int lgw_start(void) { + wait_ms(1); + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != (0x30 + i)) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + } +@@ -1036,7 +1062,7 @@ int lgw_start(void) { + wait_ms(1); + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != 0x30) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + } +@@ -1048,7 +1074,7 @@ int lgw_start(void) { + wait_ms(1); + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != 0x33) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + +@@ -1059,7 +1085,7 @@ int lgw_start(void) { + wait_ms(1); + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != 0x30) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + +@@ -1071,7 +1097,7 @@ int lgw_start(void) { + DEBUG_MSG("Info: putting back original RADIO_SELECT value\n"); + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != 0x40) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + +@@ -1080,7 +1106,7 @@ int lgw_start(void) { + + /* */ + if (lbt_is_enabled() == true) { +- printf("INFO: Configuring LBT, this may take few seconds, please wait...\n"); ++ INFO_PRINTF("Configuring LBT, this may take few seconds, please wait...\n"); + wait_ms(8400); + } + +@@ -1114,13 +1140,13 @@ int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { + + /* check if the concentrator is running */ + if (lgw_is_started == false) { +- DEBUG_MSG("ERROR: CONCENTRATOR IS NOT RUNNING, START IT BEFORE RECEIVING\n"); ++ ERROR_PRINTF("CONCENTRATOR IS NOT RUNNING, START IT BEFORE RECEIVING\n"); + return LGW_HAL_ERROR; + } + + /* check input variables */ + if ((max_pkt <= 0) || (max_pkt > LGW_PKT_FIFO_SIZE)) { +- DEBUG_PRINTF("ERROR: %d = INVALID MAX NUMBER OF PACKETS TO FETCH\n", max_pkt); ++ ERROR_PRINTF("%d = INVALID MAX NUMBER OF PACKETS TO FETCH\n", max_pkt); + return LGW_HAL_ERROR; + } + CHECK_NULL(pkt_data); +@@ -1247,7 +1273,7 @@ int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { + bw_pow = 4; + break; + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", p->bandwidth); ++ ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", p->bandwidth); + delay_x = 0; + bw_pow = 0; + } +@@ -1304,7 +1330,7 @@ int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { + /* RSSI correction */ + p->rssi = RSSI_FSK_POLY_0 + RSSI_FSK_POLY_1 * p->rssi + RSSI_FSK_POLY_2 * pow(p->rssi, 2); + } else { +- DEBUG_MSG("ERROR: UNEXPECTED PACKET ORIGIN\n"); ++ ERROR_PRINTF("UNEXPECTED PACKET ORIGIN\n"); + p->status = STAT_UNDEFINED; + p->modulation = MOD_UNDEFINED; + p->rssi = -128.0; +@@ -1347,61 +1373,61 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { + + /* check if the concentrator is running */ + if (lgw_is_started == false) { +- DEBUG_MSG("ERROR: CONCENTRATOR IS NOT RUNNING, START IT BEFORE SENDING\n"); ++ ERROR_PRINTF("CONCENTRATOR IS NOT RUNNING, START IT BEFORE SENDING\n"); + return LGW_HAL_ERROR; + } + + /* check input range (segfault prevention) */ + if (pkt_data.rf_chain >= LGW_RF_CHAIN_NB) { +- DEBUG_MSG("ERROR: INVALID RF_CHAIN TO SEND PACKETS\n"); ++ ERROR_PRINTF("INVALID RF_CHAIN TO SEND PACKETS\n"); + return LGW_HAL_ERROR; + } + + /* check input variables */ + if (rf_tx_enable[pkt_data.rf_chain] == false) { +- DEBUG_MSG("ERROR: SELECTED RF_CHAIN IS DISABLED FOR TX ON SELECTED BOARD\n"); ++ ERROR_PRINTF("SELECTED RF_CHAIN IS DISABLED FOR TX ON SELECTED BOARD\n"); + return LGW_HAL_ERROR; + } + if (rf_enable[pkt_data.rf_chain] == false) { +- DEBUG_MSG("ERROR: SELECTED RF_CHAIN IS DISABLED\n"); ++ ERROR_PRINTF("SELECTED RF_CHAIN IS DISABLED\n"); + return LGW_HAL_ERROR; + } + if (!IS_TX_MODE(pkt_data.tx_mode)) { +- DEBUG_MSG("ERROR: TX_MODE NOT SUPPORTED\n"); ++ ERROR_PRINTF("TX_MODE NOT SUPPORTED\n"); + return LGW_HAL_ERROR; + } + if (pkt_data.modulation == MOD_LORA) { + if (!IS_LORA_BW(pkt_data.bandwidth)) { +- DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA TX\n"); ++ ERROR_PRINTF("BANDWIDTH NOT SUPPORTED BY LORA TX\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_STD_DR(pkt_data.datarate)) { +- DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY LORA TX\n"); ++ ERROR_PRINTF("DATARATE NOT SUPPORTED BY LORA TX\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_CR(pkt_data.coderate)) { +- DEBUG_MSG("ERROR: CODERATE NOT SUPPORTED BY LORA TX\n"); ++ ERROR_PRINTF("CODERATE NOT SUPPORTED BY LORA TX\n"); + return LGW_HAL_ERROR; + } + if (pkt_data.size > 255) { +- DEBUG_MSG("ERROR: PAYLOAD LENGTH TOO BIG FOR LORA TX\n"); ++ ERROR_PRINTF("PAYLOAD LENGTH TOO BIG FOR LORA TX\n"); + return LGW_HAL_ERROR; + } + } else if (pkt_data.modulation == MOD_FSK) { + if((pkt_data.f_dev < 1) || (pkt_data.f_dev > 200)) { +- DEBUG_MSG("ERROR: TX FREQUENCY DEVIATION OUT OF ACCEPTABLE RANGE\n"); ++ ERROR_PRINTF("TX FREQUENCY DEVIATION OUT OF ACCEPTABLE RANGE\n"); + return LGW_HAL_ERROR; + } + if(!IS_FSK_DR(pkt_data.datarate)) { +- DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); ++ ERROR_PRINTF("DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); + return LGW_HAL_ERROR; + } + if (pkt_data.size > 255) { +- DEBUG_MSG("ERROR: PAYLOAD LENGTH TOO BIG FOR FSK TX\n"); ++ ERROR_PRINTF("PAYLOAD LENGTH TOO BIG FOR FSK TX\n"); + return LGW_HAL_ERROR; + } + } else { +- DEBUG_MSG("ERROR: INVALID TX MODULATION\n"); ++ ERROR_PRINTF("INVALID TX MODULATION\n"); + return LGW_HAL_ERROR; + } + +@@ -1448,10 +1474,15 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { + part_frac = ((pkt_data.freq_hz % (SX125x_32MHz_FRAC << 8)) << 8) / SX125x_32MHz_FRAC; /* fractional part, gives middle part and LSB */ + break; + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type[0]); ++ ERROR_PRINTF("UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type[0]); break; } - + + if( lgwx_device_mode ) { -+ pkt_data.invert_pol = false; -+ pkt_data.no_crc = false; ++ pkt_data.invert_pol = false; ++ pkt_data.no_crc = false; + } + buff[0] = 0xFF & part_int; /* Most Significant Byte */ buff[1] = 0xFF & (part_frac >> 8); /* middle byte */ buff[2] = 0xFF & part_frac; /* Least Significant Byte */ -@@ -1600,10 +1627,17 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { +@@ -1482,14 +1513,14 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { + case DR_LORA_SF10: buff[9] = 10; break; + case DR_LORA_SF11: buff[9] = 11; break; + case DR_LORA_SF12: buff[9] = 12; break; +- default: DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.datarate); ++ default: ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.datarate); + } + switch (pkt_data.coderate) { + case CR_LORA_4_5: buff[9] |= 1 << 4; break; + case CR_LORA_4_6: buff[9] |= 2 << 4; break; + case CR_LORA_4_7: buff[9] |= 3 << 4; break; + case CR_LORA_4_8: buff[9] |= 4 << 4; break; +- default: DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.coderate); ++ default: ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.coderate); + } + if (pkt_data.no_crc == false) { + buff[9] |= 0x80; /* set 'CRC enable' bit */ +@@ -1505,7 +1536,7 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { + case BW_125KHZ: buff[11] = 0; break; + case BW_250KHZ: buff[11] = 1; break; + case BW_500KHZ: buff[11] = 2; break; +- default: DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.bandwidth); ++ default: ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.bandwidth); + } + if (pkt_data.no_header == true) { + buff[11] |= 0x04; /* set 'implicit header' bit */ +@@ -1582,7 +1613,7 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { + buff[0] &= 0x7F; /* Always use narrow band for FSK (force MSB to 0) */ + + } else { +- DEBUG_MSG("ERROR: INVALID TX MODULATION..\n"); ++ ERROR_PRINTF("INVALID TX MODULATION..\n"); + return LGW_HAL_ERROR; + } + +@@ -1600,10 +1631,17 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { lgw_reg_wb(LGW_TX_DATA_BUF_DATA, buff, transfer_size); DEBUG_ARRAY(i, transfer_size, buff); - + - x = lbt_is_channel_free(&pkt_data, tx_start_delay, &tx_allowed); - if (x != LGW_LBT_SUCCESS) { - DEBUG_MSG("ERROR: Failed to check channel availability for TX\n"); - return LGW_HAL_ERROR; + if( lgwx_lbt_mode == LGWX_LBT_MODE_OFF ) { -+ tx_allowed = true; ++ tx_allowed = true; + } else { -+ //XXX:TBD: if( lgwx_lbt_mode == LGWX_LBT_MODE_EU868 ) { -+ //XXX:TBD: // change txend time so that lbt_is_channel_free checks if dead gap is within 5ms (PSA rules) -+ //XXX:TBD: } -+ x = lbt_is_channel_free(&pkt_data, tx_start_delay, &tx_allowed); -+ if (x != LGW_LBT_SUCCESS) { -+ DEBUG_MSG("ERROR: Failed to check channel availability for TX\n"); -+ return LGW_HAL_ERROR; -+ } ++ //XXX:TBD: if( lgwx_lbt_mode == LGWX_LBT_MODE_EU868 ) { ++ //XXX:TBD: // change txend time so that lbt_is_channel_free checks if dead gap is within 5ms (PSA rules) ++ //XXX:TBD: } ++ x = lbt_is_channel_free(&pkt_data, tx_start_delay, &tx_allowed); ++ if (x != LGW_LBT_SUCCESS) { ++ ERROR_PRINTF("Failed to check channel availability for TX\n"); ++ return LGW_HAL_ERROR; ++ } } if (tx_allowed == true) { switch(pkt_data.tx_mode) { +@@ -1620,11 +1658,11 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { + break; + + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.tx_mode); ++ ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.tx_mode); + return LGW_HAL_ERROR; + } + } else { +- DEBUG_MSG("ERROR: Cannot send packet, channel is busy (LBT)\n"); ++ ERROR_PRINTF("Cannot send packet, channel is busy (LBT)\n"); + return LGW_LBT_ISSUE; + } + +@@ -1657,7 +1695,7 @@ int lgw_status(uint8_t select, uint8_t *code) { + return LGW_HAL_SUCCESS; + + } else { +- DEBUG_MSG("ERROR: SELECTION INVALID, NO STATUS TO RETURN\n"); ++ ERROR_PRINTF("SELECTION INVALID, NO STATUS TO RETURN\n"); + return LGW_HAL_ERROR; + } + +@@ -1705,7 +1743,7 @@ uint32_t lgw_time_on_air(struct lgw_pkt_tx_s *packet) { + double Tsym, Tpreamble, Tpayload, Tfsk; + + if (packet == NULL) { +- DEBUG_MSG("ERROR: Failed to compute time on air, wrong parameter\n"); ++ ERROR_PRINTF("Failed to compute time on air, wrong parameter\n"); + return 0; + } + +@@ -1715,7 +1753,7 @@ uint32_t lgw_time_on_air(struct lgw_pkt_tx_s *packet) { + if (val != -1) { + BW = (uint16_t)(val / 1E3); + } else { +- DEBUG_PRINTF("ERROR: Cannot compute time on air for this packet, unsupported bandwidth (0x%02X)\n", packet->bandwidth); ++ ERROR_PRINTF("Cannot compute time on air for this packet, unsupported bandwidth (0x%02X)\n", packet->bandwidth); + return 0; + } + +@@ -1724,7 +1762,7 @@ uint32_t lgw_time_on_air(struct lgw_pkt_tx_s *packet) { + if (val != -1) { + SF = (uint8_t)val; + } else { +- DEBUG_PRINTF("ERROR: Cannot compute time on air for this packet, unsupported datarate (0x%02X)\n", packet->datarate); ++ ERROR_PRINTF("Cannot compute time on air for this packet, unsupported datarate (0x%02X)\n", packet->datarate); + return 0; + } + +@@ -1758,7 +1796,7 @@ uint32_t lgw_time_on_air(struct lgw_pkt_tx_s *packet) { + Tpacket = (uint32_t)Tfsk + 1; /* add margin for rounding */ + } else { + Tpacket = 0; +- DEBUG_PRINTF("ERROR: Cannot compute time on air for this packet, unsupported modulation (0x%02X)\n", packet->modulation); ++ ERROR_PRINTF("Cannot compute time on air for this packet, unsupported modulation (0x%02X)\n", packet->modulation); + } + + return Tpacket; +diff --git a/libloragw/src/loragw_lbt.c b/libloragw/src/loragw_lbt.c +index 9c43521..515e9ac 100644 +--- a/libloragw/src/loragw_lbt.c ++++ b/libloragw/src/loragw_lbt.c +@@ -41,6 +41,8 @@ Maintainer: Michael Coracin + #define CHECK_NULL(a) if(a==NULL){return LGW_REG_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + #define LBT_TIMESTAMP_MASK 0x007FF000 /* 11-bits timestamp */ + + /* -------------------------------------------------------------------------- */ +@@ -326,7 +328,7 @@ int lbt_is_channel_free(struct lgw_pkt_tx_s * pkt_data, uint16_t tx_start_delay, + delta_time = tx_end_time - lbt_time; + } else { + /* It means LBT counter has wrapped */ +- printf("LBT: lbt counter has wrapped\n"); ++ DEBUG_PRINTF("LBT: lbt counter has wrapped\n"); + delta_time = (LBT_TIMESTAMP_MASK - lbt_time) + tx_end_time; + } + +diff --git a/libloragw/src/loragw_radio.c b/libloragw/src/loragw_radio.c +index b3046a9..a01f65b 100644 +--- a/libloragw/src/loragw_radio.c ++++ b/libloragw/src/loragw_radio.c +@@ -46,6 +46,8 @@ Maintainer: Michael Coracin + #define CHECK_NULL(a) if(a==NULL){return LGW_REG_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE TYPES -------------------------------------------------------- */ + +diff --git a/libloragw/src/loragw_reg.c b/libloragw/src/loragw_reg.c +index 14e23cd..6d8aab3 100644 +--- a/libloragw/src/loragw_reg.c ++++ b/libloragw/src/loragw_reg.c +@@ -42,6 +42,8 @@ Maintainer: Sylvain Miermont + #define CHECK_NULL(a) if(a==NULL){return LGW_REG_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + diff --git a/libloragw/src/loragw_spi.native.c b/libloragw/src/loragw_spi.native.c -index c01ed1c..0e2b64c 100644 +index c01ed1c..7cc7eea 100644 --- a/libloragw/src/loragw_spi.native.c +++ b/libloragw/src/loragw_spi.native.c -@@ -54,7 +54,7 @@ Maintainer: Sylvain Miermont +@@ -48,13 +48,15 @@ Maintainer: Sylvain Miermont + #define CHECK_NULL(a) if(a==NULL){return LGW_SPI_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + #define READ_ACCESS 0x00 #define WRITE_ACCESS 0x80 - #define SPI_SPEED 8000000 +-#define SPI_SPEED 8000000 -#define SPI_DEV_PATH "/dev/spidev0.0" ++#define SPI_SPEED (getenv("LORAGW_SPI_SPEED")==NULL ? 8000000 : atoi(getenv("LORAGW_SPI_SPEED"))) +#define SPI_DEV_PATH (getenv("LORAGW_SPI")==NULL ? "/dev/spidev0.0" : getenv("LORAGW_SPI")) //#define SPI_DEV_PATH "/dev/spidev32766.0" - + /* -------------------------------------------------------------------------- */ +@@ -96,6 +98,7 @@ int lgw_spi_open(void **spi_target_ptr) { + } + + /* setting SPI max clk (in Hz) */ ++ INFO_PRINTF("Setting SPI speed to %u\n", SPI_SPEED); + i = SPI_SPEED; + a = ioctl(dev, SPI_IOC_WR_MAX_SPEED_HZ, &i); + b = ioctl(dev, SPI_IOC_RD_MAX_SPEED_HZ, &i); +@@ -111,7 +114,7 @@ int lgw_spi_open(void **spi_target_ptr) { + 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"); ++ ERROR_PRINTF("SPI PORT FAIL TO SET MSB FIRST\n"); + close(dev); + free(spi_device); + return LGW_SPI_ERROR; +@@ -122,14 +125,14 @@ int lgw_spi_open(void **spi_target_ptr) { + 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"); ++ ERROR_PRINTF("SPI PORT FAIL TO SET 8 BITS-PER-WORD\n"); + close(dev); + return LGW_SPI_ERROR; + } + + *spi_device = dev; + *spi_target_ptr = (void *)spi_device; +- DEBUG_MSG("Note: SPI port opened and configured ok\n"); ++ INFO_PRINTF("Note: SPI port opened and configured ok\n"); + return LGW_SPI_SUCCESS; + } + +@@ -150,10 +153,10 @@ int lgw_spi_close(void *spi_target) { + + /* determine return code */ + if (a < 0) { +- DEBUG_MSG("ERROR: SPI PORT FAILED TO CLOSE\n"); ++ ERROR_PRINTF("SPI PORT FAILED TO CLOSE\n"); + return LGW_SPI_ERROR; + } else { +- DEBUG_MSG("Note: SPI port closed\n"); ++ INFO_PRINTF("Note: SPI port closed\n"); + return LGW_SPI_SUCCESS; + } + } +@@ -199,7 +202,7 @@ int lgw_spi_w(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, ui + + /* determine return code */ + if (a != (int)k.len) { +- DEBUG_MSG("ERROR: SPI WRITE FAILURE\n"); ++ ERROR_PRINTF("SPI WRITE FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI write success\n"); +@@ -249,7 +252,7 @@ int lgw_spi_r(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, ui + + /* determine return code */ + if (a != (int)k.len) { +- DEBUG_MSG("ERROR: SPI READ FAILURE\n"); ++ ERROR_PRINTF("SPI READ FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI read success\n"); +@@ -277,7 +280,7 @@ int lgw_spi_wb(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, u + } + CHECK_NULL(data); + if (size == 0) { +- DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); ++ ERROR_PRINTF("BURST OF NULL LENGTH\n"); + return LGW_SPI_ERROR; + } + +@@ -312,7 +315,7 @@ int lgw_spi_wb(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, u + + /* determine return code */ + if (byte_transfered != size) { +- DEBUG_MSG("ERROR: SPI BURST WRITE FAILURE\n"); ++ ERROR_PRINTF("SPI BURST WRITE FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI burst write success\n"); +@@ -339,7 +342,7 @@ int lgw_spi_rb(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, u + } + CHECK_NULL(data); + if (size == 0) { +- DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); ++ ERROR_PRINTF("ERROR: BURST OF NULL LENGTH\n"); + return LGW_SPI_ERROR; + } + +@@ -368,16 +371,16 @@ int lgw_spi_rb(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, u + k[1].rx_buf = (unsigned long)(data + offset); + k[1].len = chunk_size; + byte_transfered += (ioctl(spi_device, SPI_IOC_MESSAGE(2), &k) - k[0].len ); +- DEBUG_PRINTF("BURST READ: to trans %d # chunk %d # transferred %d \n", size_to_do, chunk_size, byte_transfered); ++ // 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"); ++ ERROR_PRINTF("ERROR: SPI BURST READ FAILURE\n"); + return LGW_SPI_ERROR; + } else { +- DEBUG_MSG("Note: SPI burst read success\n"); ++ // DEBUG_MSG("Note: SPI burst read success\n"); + return LGW_SPI_SUCCESS; + } + } diff --git a/deps/lgw/v5.0.1-rpi.patch b/deps/lgw/v5.0.1-rpi.patch index 8a2281b..3c1aaf6 100644 --- a/deps/lgw/v5.0.1-rpi.patch +++ b/deps/lgw/v5.0.1-rpi.patch @@ -1,15 +1,20 @@ diff --git a/libloragw/Makefile b/libloragw/Makefile -index 53c33d9..a8a09a2 100644 +index 53c33d9..cc7d016 100644 --- a/libloragw/Makefile +++ b/libloragw/Makefile -@@ -7,6 +7,7 @@ include library.cfg - +@@ -7,10 +7,12 @@ include library.cfg + ARCH ?= CROSS_COMPILE ?= + CC := $(CROSS_COMPILE)gcc AR := $(CROSS_COMPILE)ar - + + CFLAGS := -O2 -Wall -Wextra -std=c99 -Iinc -I. ++CFLAGS += ${EXTRA_CFLAGS} + + OBJDIR = obj + INCLUDES = $(wildcard inc/*.h) diff --git a/libloragw/inc/loragw_hal.h b/libloragw/inc/loragw_hal.h index d5f9ade..57927c4 100644 --- a/libloragw/inc/loragw_hal.h @@ -17,7 +22,7 @@ index d5f9ade..57927c4 100644 @@ -414,6 +414,12 @@ const char* lgw_version_info(void); */ uint32_t lgw_time_on_air(struct lgw_pkt_tx_s *packet); - + +extern uint8_t lgwx_device_mode; +extern uint8_t lgwx_beacon_len; +extern uint8_t lgwx_beacon_sf; @@ -25,109 +30,1070 @@ index d5f9ade..57927c4 100644 +enum { LGWX_LBT_MODE_DFLT=0, LGWX_LBT_MODE_OFF = 1 }; + #endif - + /* --- EOF ------------------------------------------------------------------ */ +diff --git a/libloragw/inc/loragw_stationlog.h b/libloragw/inc/loragw_stationlog.h +new file mode 100644 +index 0000000..a282b8f +--- /dev/null ++++ b/libloragw/inc/loragw_stationlog.h +@@ -0,0 +1,26 @@ ++#ifndef _LORAGW_STATIONLOG_H ++#define _LORAGW_STATIONLOG_H ++ ++#if defined(STATIONLOG) ++ ++#undef DEBUG_PRINTF ++#undef DEBUG_MSG ++ ++enum { XDEBUG=0, DEBUG, VERBOSE, INFO, NOTICE, WARNING, ERROR, CRITICAL }; ++extern void log_hal (uint8_t level, const char* fmt, ...); ++#define ERROR_PRINTF(fmt, ...) log_hal(ERROR , "[%s:%d] "fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__) ++#define INFO_PRINTF(fmt, ...) log_hal(INFO , "[%s:%d] "fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__) ++#define DEBUG_PRINTF(fmt, ...) log_hal(XDEBUG , "[%s:%d] "fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__) ++#define DEBUG_MSG(str) log_hal(XDEBUG , "[%s:%d] %s", __FUNCTION__, __LINE__, str) ++#define XDEBUG_PRINTF(fmt, ...) log_hal(XDEBUG , "[%s:%d] "fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__) ++#define XDEBUG_MSG(str) log_hal(XDEBUG , "[%s:%d] %s", __FUNCTION__, __LINE__, str) ++ ++#else // !defined(STATIONLOG) ++ ++#define ERROR_PRINTF(fmt, ...) DEBUG_PRINTF(fmt, ## __VA_ARGS__) ++#define INFO_PRINTF(fmt, ...) DEBUG_PRINTF(fmt, ## __VA_ARGS__) ++#define XDEBUG_PRINTF(fmt, ...) DEBUG_PRINTF(fmt, ## __VA_ARGS__) ++#define XDEBUG_MSG(str) DEBUG_MSG(str) ++#endif ++ ++#endif +diff --git a/libloragw/src/loragw_fpga.c b/libloragw/src/loragw_fpga.c +index 465f43e..9b98786 100644 +--- a/libloragw/src/loragw_fpga.c ++++ b/libloragw/src/loragw_fpga.c +@@ -43,6 +43,8 @@ Maintainer: Michael Coracin + #define CHECK_NULL(a) if(a==NULL){return LGW_REG_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + +@@ -140,21 +142,16 @@ int lgw_fpga_configure(uint32_t tx_notch_freq) { + } + + /* Get supported FPGA features */ +- printf("INFO: FPGA supported features:"); + lgw_fpga_reg_r(LGW_FPGA_FEATURE, &val); + tx_notch_support = TAKE_N_BITS_FROM((uint8_t)val, 0, 1); +- if (tx_notch_support == true) { +- printf(" [TX filter] "); +- } + spectral_scan_support = TAKE_N_BITS_FROM((uint8_t)val, 1, 1); +- if (spectral_scan_support == true) { +- printf(" [Spectral Scan] "); +- } + lbt_support = TAKE_N_BITS_FROM((uint8_t)val, 2, 1); +- if (lbt_support == true) { +- printf(" [LBT] "); +- } +- printf("\n"); ++ ++ INFO_PRINTF("INFO: FPGA supported features: %s%s%s", ++ tx_notch_support ? " [TX filter] " : "", ++ spectral_scan_support ? " [Spectral Scan] " : "", ++ lbt_support ? " [lbt_support] " : "" ++ ); + + x = lgw_fpga_reg_w(LGW_FPGA_CTRL_INPUT_SYNC_I, 1); + x |= lgw_fpga_reg_w(LGW_FPGA_CTRL_INPUT_SYNC_Q, 1); +diff --git a/libloragw/src/loragw_gps.c b/libloragw/src/loragw_gps.c +index c0e0ded..14eff6e 100644 +--- a/libloragw/src/loragw_gps.c ++++ b/libloragw/src/loragw_gps.c +@@ -39,16 +39,20 @@ Maintainer: Michael Coracin + + #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + #if DEBUG_GPS == 1 +- #define DEBUG_MSG(args...) fprintf(stderr, args) ++ #define DEBUG_MSG(str) fprintf(stderr, str) ++ #define DEBUG_PRINTF(fmt, args...) fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args) + #define DEBUG_ARRAY(a,b,c) for(a=0;a %H", buff_size, serial_buff); ++#else + DEBUG_MSG("Note: parsing UBX frame> "); + for (i=0; i= LGW_RF_CHAIN_NB) { +- DEBUG_MSG("ERROR: NOT A VALID RF_CHAIN NUMBER\n"); ++ ERROR_PRINTF("NOT A VALID RF_CHAIN NUMBER\n"); + return LGW_HAL_ERROR; + } + + /* check if radio type is supported */ + if ((conf.type != LGW_RADIO_TYPE_SX1255) && (conf.type != LGW_RADIO_TYPE_SX1257)) { +- DEBUG_MSG("ERROR: NOT A VALID RADIO TYPE\n"); ++ ERROR_PRINTF("NOT A VALID RADIO TYPE\n"); + return LGW_HAL_ERROR; + } + +@@ -498,13 +524,13 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + + /* check if the concentrator is running */ + if (lgw_is_started == true) { +- DEBUG_MSG("ERROR: CONCENTRATOR IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); ++ ERROR_PRINTF("CONCENTRATOR IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); + return LGW_HAL_ERROR; + } + + /* check input range (segfault prevention) */ + if (if_chain >= LGW_IF_CHAIN_NB) { +- DEBUG_PRINTF("ERROR: %d NOT A VALID IF_CHAIN NUMBER\n", if_chain); ++ ERROR_PRINTF("%d NOT A VALID IF_CHAIN NUMBER\n", if_chain); + return LGW_HAL_ERROR; + } + +@@ -518,10 +544,10 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + + /* check 'general' parameters */ + if (ifmod_config[if_chain] == IF_UNDEFINED) { +- DEBUG_PRINTF("ERROR: IF CHAIN %d NOT CONFIGURABLE\n", if_chain); ++ ERROR_PRINTF("IF CHAIN %d NOT CONFIGURABLE\n", if_chain); + } + if (conf.rf_chain >= LGW_RF_CHAIN_NB) { +- DEBUG_MSG("ERROR: INVALID RF_CHAIN TO ASSOCIATE WITH A LORA_STD IF CHAIN\n"); ++ ERROR_PRINTF("INVALID RF_CHAIN TO ASSOCIATE WITH A LORA_STD IF CHAIN\n"); + return LGW_HAL_ERROR; + } + /* check if IF frequency is optimal based on channel and radio bandwidths */ +@@ -539,10 +565,10 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + } + bw_hz = lgw_bw_getval(conf.bandwidth); /* channel bandwidth */ + if ((conf.freq_hz + ((bw_hz==-1)?LGW_REF_BW:bw_hz)/2) > ((int32_t)rf_rx_bandwidth/2)) { +- DEBUG_PRINTF("ERROR: IF FREQUENCY %d TOO HIGH\n", conf.freq_hz); ++ ERROR_PRINTF("IF FREQUENCY %d TOO HIGH\n", conf.freq_hz); + return LGW_HAL_ERROR; + } else if ((conf.freq_hz - ((bw_hz==-1)?LGW_REF_BW:bw_hz)/2) < -((int32_t)rf_rx_bandwidth/2)) { +- DEBUG_PRINTF("ERROR: IF FREQUENCY %d TOO LOW\n", conf.freq_hz); ++ ERROR_PRINTF("IF FREQUENCY %d TOO LOW\n", conf.freq_hz); + return LGW_HAL_ERROR; + } + +@@ -559,11 +585,11 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + } + /* check BW & DR */ + if (!IS_LORA_BW(conf.bandwidth)) { +- DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA_STD IF CHAIN\n"); ++ ERROR_PRINTF("BANDWIDTH NOT SUPPORTED BY LORA_STD IF CHAIN\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_STD_DR(conf.datarate)) { +- DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY LORA_STD IF CHAIN\n"); ++ ERROR_PRINTF("DATARATE NOT SUPPORTED BY LORA_STD IF CHAIN\n"); + return LGW_HAL_ERROR; + } + /* set internal configuration */ +@@ -591,11 +617,11 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + } + /* check BW & DR */ + if (conf.bandwidth != BW_125KHZ) { +- DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); ++ ERROR_PRINTF("BANDWIDTH NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_MULTI_DR(conf.datarate)) { +- DEBUG_MSG("ERROR: DATARATE(S) NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); ++ ERROR_PRINTF("DATARATE(S) NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); + return LGW_HAL_ERROR; + } + /* set internal configuration */ +@@ -617,11 +643,11 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + } + /* check BW & DR */ + if(!IS_FSK_BW(conf.bandwidth)) { +- DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY FSK IF CHAIN\n"); ++ ERROR_PRINTF("BANDWIDTH NOT SUPPORTED BY FSK IF CHAIN\n"); + return LGW_HAL_ERROR; + } + if(!IS_FSK_DR(conf.datarate)) { +- DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); ++ ERROR_PRINTF("DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); + return LGW_HAL_ERROR; + } + /* set internal configuration */ +@@ -638,7 +664,7 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + break; + + default: +- DEBUG_PRINTF("ERROR: IF CHAIN %d TYPE NOT SUPPORTED\n", if_chain); ++ ERROR_PRINTF("IF CHAIN %d TYPE NOT SUPPORTED\n", if_chain); + return LGW_HAL_ERROR; + } + +@@ -652,7 +678,7 @@ int lgw_txgain_setconf(struct lgw_tx_gain_lut_s *conf) { + + /* Check LUT size */ + if ((conf->size < 1) || (conf->size > TX_GAIN_LUT_SIZE_MAX)) { +- DEBUG_PRINTF("ERROR: TX gain LUT must have at least one entry and maximum %d entries\n", TX_GAIN_LUT_SIZE_MAX); ++ ERROR_PRINTF("TX gain LUT must have at least one entry and maximum %d entries\n", TX_GAIN_LUT_SIZE_MAX); + return LGW_HAL_ERROR; + } + +@@ -661,22 +687,22 @@ int lgw_txgain_setconf(struct lgw_tx_gain_lut_s *conf) { + for (i = 0; i < txgain_lut.size; i++) { + /* Check gain range */ + if (conf->lut[i].dig_gain > 3) { +- DEBUG_MSG("ERROR: TX gain LUT: SX1301 digital gain must be between 0 and 3\n"); ++ ERROR_PRINTF("TX gain LUT: SX1301 digital gain must be between 0 and 3\n"); + return LGW_HAL_ERROR; + } + if (conf->lut[i].dac_gain != 3) { +- DEBUG_MSG("ERROR: TX gain LUT: SX1257 DAC gains != 3 are not supported\n"); ++ ERROR_PRINTF("TX gain LUT: SX1257 DAC gains != 3 are not supported\n"); + return LGW_HAL_ERROR; + } + if (conf->lut[i].mix_gain > 15) { +- DEBUG_MSG("ERROR: TX gain LUT: SX1257 mixer gain must not exceed 15\n"); ++ ERROR_PRINTF("TX gain LUT: SX1257 mixer gain must not exceed 15\n"); + return LGW_HAL_ERROR; + } else if (conf->lut[i].mix_gain < 8) { +- DEBUG_MSG("ERROR: TX gain LUT: SX1257 mixer gains < 8 are not supported\n"); ++ ERROR_PRINTF("TX gain LUT: SX1257 mixer gains < 8 are not supported\n"); + return LGW_HAL_ERROR; + } + if (conf->lut[i].pa_gain > 3) { +- DEBUG_MSG("ERROR: TX gain LUT: External PA gain must not exceed 3\n"); ++ ERROR_PRINTF("TX gain LUT: External PA gain must not exceed 3\n"); + return LGW_HAL_ERROR; + } + +@@ -713,7 +739,7 @@ int lgw_start(void) { + + reg_stat = lgw_connect(false, rf_tx_notch_freq[rf_tx_enable[1]?1:0]); + if (reg_stat == LGW_REG_ERROR) { +- DEBUG_MSG("ERROR: FAIL TO CONNECT BOARD\n"); ++ ERROR_PRINTF("FAIL TO CONNECT BOARD\n"); + return LGW_HAL_ERROR; + } + +@@ -735,12 +761,12 @@ int lgw_start(void) { + /* setup the radios */ + err = lgw_setup_sx125x(0, rf_clkout, rf_enable[0], rf_radio_type[0], rf_rx_freq[0]); + if (err != 0) { +- DEBUG_MSG("ERROR: Failed to setup sx125x radio for RF chain 0\n"); ++ ERROR_PRINTF("Failed to setup sx125x radio for RF chain 0\n"); + return LGW_HAL_ERROR; + } + err = lgw_setup_sx125x(1, rf_clkout, rf_enable[1], rf_radio_type[1], rf_rx_freq[1]); + if (err != 0) { +- DEBUG_MSG("ERROR: Failed to setup sx125x radio for RF chain 0\n"); ++ ERROR_PRINTF("Failed to setup sx125x radio for RF chain 0\n"); + return LGW_HAL_ERROR; + } + +@@ -753,7 +779,7 @@ int lgw_start(void) { + lgw_reg_w(LGW_CLK32M_EN, 1); + i = lbt_setup(); + if (i != LGW_LBT_SUCCESS) { +- DEBUG_MSG("ERROR: lbt_setup() did not return SUCCESS\n"); ++ ERROR_PRINTF("lbt_setup() did not return SUCCESS\n"); + return LGW_HAL_ERROR; + } + +@@ -761,7 +787,7 @@ int lgw_start(void) { + lgw_reg_w(LGW_CLK32M_EN, 0); + i = lbt_start(); + if (i != LGW_LBT_SUCCESS) { +- DEBUG_MSG("ERROR: lbt_start() did not return SUCCESS\n"); ++ ERROR_PRINTF("lbt_start() did not return SUCCESS\n"); + return LGW_HAL_ERROR; + } + } +@@ -794,7 +820,7 @@ int lgw_start(void) { + cal_cmd |= 0x00; /* Bit 5: 0: SX1257, 1: SX1255 */ + break; + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type[0]); ++ ERROR_PRINTF("UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type[0]); + break; + } + +@@ -812,7 +838,7 @@ int lgw_start(void) { + lgw_reg_r(LGW_DBG_AGC_MCU_RAM_DATA, &read_val); + fw_version = (uint8_t)read_val; + if (fw_version != FW_VERSION_CAL) { +- printf("ERROR: Version of calibration firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_CAL); ++ ERROR_PRINTF("Version of calibration firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_CAL); + return -1; + } + +@@ -838,7 +864,7 @@ int lgw_start(void) { + bit 6: radio B TX DC Offset correction successful + */ + if ((cal_status & 0x81) != 0x81) { +- DEBUG_PRINTF("ERROR: CALIBRATION FAILURE (STATUS = %u)\n", cal_status); ++ ERROR_PRINTF("CALIBRATION FAILURE (STATUS = %u)\n", cal_status); + return LGW_HAL_ERROR; + } else { + DEBUG_PRINTF("Note: calibration finished (status = %u)\n", cal_status); +@@ -883,7 +909,7 @@ int lgw_start(void) { + + /* Sanity check for RX frequency */ + if (rf_rx_freq[0] == 0) { +- DEBUG_MSG("ERROR: wrong configuration, rf_rx_freq[0] is not set\n"); ++ ERROR_PRINTF("wrong configuration, rf_rx_freq[0] is not set\n"); + return LGW_HAL_ERROR; + } + +@@ -939,7 +965,7 @@ int lgw_start(void) { + case BW_250KHZ: lgw_reg_w(LGW_MBWSSF_MODEM_BW, 1); break; + case BW_500KHZ: lgw_reg_w(LGW_MBWSSF_MODEM_BW, 2); break; + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", lora_rx_bw); ++ ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", lora_rx_bw); + return LGW_HAL_ERROR; + } + switch(lora_rx_sf) { +@@ -950,7 +976,7 @@ int lgw_start(void) { + case DR_LORA_SF11: lgw_reg_w(LGW_MBWSSF_RATE_SF, 11); break; + case DR_LORA_SF12: lgw_reg_w(LGW_MBWSSF_RATE_SF, 12); break; + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", lora_rx_sf); ++ ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", lora_rx_sf); + return LGW_HAL_ERROR; + } + lgw_reg_w(LGW_MBWSSF_PPM_OFFSET, lora_rx_ppm_offset); /* default 0 */ +@@ -994,14 +1020,14 @@ int lgw_start(void) { + lgw_reg_r(LGW_DBG_AGC_MCU_RAM_DATA, &read_val); + fw_version = (uint8_t)read_val; + if (fw_version != FW_VERSION_AGC) { +- DEBUG_PRINTF("ERROR: Version of AGC firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_AGC); ++ ERROR_PRINTF("Version of AGC firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_AGC); + return LGW_HAL_ERROR; + } + lgw_reg_w(LGW_DBG_ARB_MCU_RAM_ADDR, FW_VERSION_ADDR); + lgw_reg_r(LGW_DBG_ARB_MCU_RAM_DATA, &read_val); + fw_version = (uint8_t)read_val; + if (fw_version != FW_VERSION_ARB) { +- DEBUG_PRINTF("ERROR: Version of arbiter firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_ARB); ++ ERROR_PRINTF("Version of arbiter firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_ARB); + return LGW_HAL_ERROR; + } + +@@ -1010,7 +1036,7 @@ int lgw_start(void) { + + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != 0x10) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + +@@ -1023,7 +1049,7 @@ int lgw_start(void) { + wait_ms(1); + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != (0x30 + i)) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + } +@@ -1036,7 +1062,7 @@ int lgw_start(void) { + wait_ms(1); + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != 0x30) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + } +@@ -1048,7 +1074,7 @@ int lgw_start(void) { + wait_ms(1); + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != 0x33) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + +@@ -1059,7 +1085,7 @@ int lgw_start(void) { + wait_ms(1); + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != 0x30) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + +@@ -1071,7 +1097,7 @@ int lgw_start(void) { + DEBUG_MSG("Info: putting back original RADIO_SELECT value\n"); + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != 0x40) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + +@@ -1080,7 +1106,7 @@ int lgw_start(void) { + + /* */ + if (lbt_is_enabled() == true) { +- printf("INFO: Configuring LBT, this may take few seconds, please wait...\n"); ++ INFO_PRINTF("Configuring LBT, this may take few seconds, please wait...\n"); + wait_ms(8400); + } + +@@ -1114,13 +1140,13 @@ int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { + + /* check if the concentrator is running */ + if (lgw_is_started == false) { +- DEBUG_MSG("ERROR: CONCENTRATOR IS NOT RUNNING, START IT BEFORE RECEIVING\n"); ++ ERROR_PRINTF("CONCENTRATOR IS NOT RUNNING, START IT BEFORE RECEIVING\n"); + return LGW_HAL_ERROR; + } + + /* check input variables */ + if ((max_pkt <= 0) || (max_pkt > LGW_PKT_FIFO_SIZE)) { +- DEBUG_PRINTF("ERROR: %d = INVALID MAX NUMBER OF PACKETS TO FETCH\n", max_pkt); ++ ERROR_PRINTF("%d = INVALID MAX NUMBER OF PACKETS TO FETCH\n", max_pkt); + return LGW_HAL_ERROR; + } + CHECK_NULL(pkt_data); +@@ -1247,7 +1273,7 @@ int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { + bw_pow = 4; + break; + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", p->bandwidth); ++ ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", p->bandwidth); + delay_x = 0; + bw_pow = 0; + } +@@ -1304,7 +1330,7 @@ int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { + /* RSSI correction */ + p->rssi = RSSI_FSK_POLY_0 + RSSI_FSK_POLY_1 * p->rssi + RSSI_FSK_POLY_2 * pow(p->rssi, 2); + } else { +- DEBUG_MSG("ERROR: UNEXPECTED PACKET ORIGIN\n"); ++ ERROR_PRINTF("UNEXPECTED PACKET ORIGIN\n"); + p->status = STAT_UNDEFINED; + p->modulation = MOD_UNDEFINED; + p->rssi = -128.0; +@@ -1347,61 +1373,61 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { + + /* check if the concentrator is running */ + if (lgw_is_started == false) { +- DEBUG_MSG("ERROR: CONCENTRATOR IS NOT RUNNING, START IT BEFORE SENDING\n"); ++ ERROR_PRINTF("CONCENTRATOR IS NOT RUNNING, START IT BEFORE SENDING\n"); + return LGW_HAL_ERROR; + } + + /* check input range (segfault prevention) */ + if (pkt_data.rf_chain >= LGW_RF_CHAIN_NB) { +- DEBUG_MSG("ERROR: INVALID RF_CHAIN TO SEND PACKETS\n"); ++ ERROR_PRINTF("INVALID RF_CHAIN TO SEND PACKETS\n"); + return LGW_HAL_ERROR; + } + + /* check input variables */ + if (rf_tx_enable[pkt_data.rf_chain] == false) { +- DEBUG_MSG("ERROR: SELECTED RF_CHAIN IS DISABLED FOR TX ON SELECTED BOARD\n"); ++ ERROR_PRINTF("SELECTED RF_CHAIN IS DISABLED FOR TX ON SELECTED BOARD\n"); + return LGW_HAL_ERROR; + } + if (rf_enable[pkt_data.rf_chain] == false) { +- DEBUG_MSG("ERROR: SELECTED RF_CHAIN IS DISABLED\n"); ++ ERROR_PRINTF("SELECTED RF_CHAIN IS DISABLED\n"); + return LGW_HAL_ERROR; + } + if (!IS_TX_MODE(pkt_data.tx_mode)) { +- DEBUG_MSG("ERROR: TX_MODE NOT SUPPORTED\n"); ++ ERROR_PRINTF("TX_MODE NOT SUPPORTED\n"); + return LGW_HAL_ERROR; + } + if (pkt_data.modulation == MOD_LORA) { + if (!IS_LORA_BW(pkt_data.bandwidth)) { +- DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA TX\n"); ++ ERROR_PRINTF("BANDWIDTH NOT SUPPORTED BY LORA TX\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_STD_DR(pkt_data.datarate)) { +- DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY LORA TX\n"); ++ ERROR_PRINTF("DATARATE NOT SUPPORTED BY LORA TX\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_CR(pkt_data.coderate)) { +- DEBUG_MSG("ERROR: CODERATE NOT SUPPORTED BY LORA TX\n"); ++ ERROR_PRINTF("CODERATE NOT SUPPORTED BY LORA TX\n"); + return LGW_HAL_ERROR; + } + if (pkt_data.size > 255) { +- DEBUG_MSG("ERROR: PAYLOAD LENGTH TOO BIG FOR LORA TX\n"); ++ ERROR_PRINTF("PAYLOAD LENGTH TOO BIG FOR LORA TX\n"); + return LGW_HAL_ERROR; + } + } else if (pkt_data.modulation == MOD_FSK) { + if((pkt_data.f_dev < 1) || (pkt_data.f_dev > 200)) { +- DEBUG_MSG("ERROR: TX FREQUENCY DEVIATION OUT OF ACCEPTABLE RANGE\n"); ++ ERROR_PRINTF("TX FREQUENCY DEVIATION OUT OF ACCEPTABLE RANGE\n"); + return LGW_HAL_ERROR; + } + if(!IS_FSK_DR(pkt_data.datarate)) { +- DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); ++ ERROR_PRINTF("DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); + return LGW_HAL_ERROR; + } + if (pkt_data.size > 255) { +- DEBUG_MSG("ERROR: PAYLOAD LENGTH TOO BIG FOR FSK TX\n"); ++ ERROR_PRINTF("PAYLOAD LENGTH TOO BIG FOR FSK TX\n"); + return LGW_HAL_ERROR; + } + } else { +- DEBUG_MSG("ERROR: INVALID TX MODULATION\n"); ++ ERROR_PRINTF("INVALID TX MODULATION\n"); + return LGW_HAL_ERROR; + } + +@@ -1448,10 +1474,15 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { + part_frac = ((pkt_data.freq_hz % (SX125x_32MHz_FRAC << 8)) << 8) / SX125x_32MHz_FRAC; /* fractional part, gives middle part and LSB */ + break; + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type[0]); ++ ERROR_PRINTF("UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type[0]); break; } - + + if( lgwx_device_mode ) { -+ pkt_data.invert_pol = false; -+ pkt_data.no_crc = false; ++ pkt_data.invert_pol = false; ++ pkt_data.no_crc = false; + } + buff[0] = 0xFF & part_int; /* Most Significant Byte */ buff[1] = 0xFF & (part_frac >> 8); /* middle byte */ buff[2] = 0xFF & part_frac; /* Least Significant Byte */ -@@ -1600,10 +1627,17 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { +@@ -1482,14 +1513,14 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { + case DR_LORA_SF10: buff[9] = 10; break; + case DR_LORA_SF11: buff[9] = 11; break; + case DR_LORA_SF12: buff[9] = 12; break; +- default: DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.datarate); ++ default: ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.datarate); + } + switch (pkt_data.coderate) { + case CR_LORA_4_5: buff[9] |= 1 << 4; break; + case CR_LORA_4_6: buff[9] |= 2 << 4; break; + case CR_LORA_4_7: buff[9] |= 3 << 4; break; + case CR_LORA_4_8: buff[9] |= 4 << 4; break; +- default: DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.coderate); ++ default: ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.coderate); + } + if (pkt_data.no_crc == false) { + buff[9] |= 0x80; /* set 'CRC enable' bit */ +@@ -1505,7 +1536,7 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { + case BW_125KHZ: buff[11] = 0; break; + case BW_250KHZ: buff[11] = 1; break; + case BW_500KHZ: buff[11] = 2; break; +- default: DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.bandwidth); ++ default: ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.bandwidth); + } + if (pkt_data.no_header == true) { + buff[11] |= 0x04; /* set 'implicit header' bit */ +@@ -1582,7 +1613,7 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { + buff[0] &= 0x7F; /* Always use narrow band for FSK (force MSB to 0) */ + + } else { +- DEBUG_MSG("ERROR: INVALID TX MODULATION..\n"); ++ ERROR_PRINTF("INVALID TX MODULATION..\n"); + return LGW_HAL_ERROR; + } + +@@ -1600,10 +1631,17 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { lgw_reg_wb(LGW_TX_DATA_BUF_DATA, buff, transfer_size); DEBUG_ARRAY(i, transfer_size, buff); - + - x = lbt_is_channel_free(&pkt_data, tx_start_delay, &tx_allowed); - if (x != LGW_LBT_SUCCESS) { - DEBUG_MSG("ERROR: Failed to check channel availability for TX\n"); - return LGW_HAL_ERROR; + if( lgwx_lbt_mode == LGWX_LBT_MODE_OFF ) { -+ tx_allowed = true; ++ tx_allowed = true; + } else { -+ //XXX:TBD: if( lgwx_lbt_mode == LGWX_LBT_MODE_EU868 ) { -+ //XXX:TBD: // change txend time so that lbt_is_channel_free checks if dead gap is within 5ms (PSA rules) -+ //XXX:TBD: } -+ x = lbt_is_channel_free(&pkt_data, tx_start_delay, &tx_allowed); -+ if (x != LGW_LBT_SUCCESS) { -+ DEBUG_MSG("ERROR: Failed to check channel availability for TX\n"); -+ return LGW_HAL_ERROR; -+ } ++ //XXX:TBD: if( lgwx_lbt_mode == LGWX_LBT_MODE_EU868 ) { ++ //XXX:TBD: // change txend time so that lbt_is_channel_free checks if dead gap is within 5ms (PSA rules) ++ //XXX:TBD: } ++ x = lbt_is_channel_free(&pkt_data, tx_start_delay, &tx_allowed); ++ if (x != LGW_LBT_SUCCESS) { ++ ERROR_PRINTF("Failed to check channel availability for TX\n"); ++ return LGW_HAL_ERROR; ++ } } if (tx_allowed == true) { switch(pkt_data.tx_mode) { +@@ -1620,11 +1658,11 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { + break; + + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.tx_mode); ++ ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", pkt_data.tx_mode); + return LGW_HAL_ERROR; + } + } else { +- DEBUG_MSG("ERROR: Cannot send packet, channel is busy (LBT)\n"); ++ ERROR_PRINTF("Cannot send packet, channel is busy (LBT)\n"); + return LGW_LBT_ISSUE; + } + +@@ -1657,7 +1695,7 @@ int lgw_status(uint8_t select, uint8_t *code) { + return LGW_HAL_SUCCESS; + + } else { +- DEBUG_MSG("ERROR: SELECTION INVALID, NO STATUS TO RETURN\n"); ++ ERROR_PRINTF("SELECTION INVALID, NO STATUS TO RETURN\n"); + return LGW_HAL_ERROR; + } + +@@ -1705,7 +1743,7 @@ uint32_t lgw_time_on_air(struct lgw_pkt_tx_s *packet) { + double Tsym, Tpreamble, Tpayload, Tfsk; + + if (packet == NULL) { +- DEBUG_MSG("ERROR: Failed to compute time on air, wrong parameter\n"); ++ ERROR_PRINTF("Failed to compute time on air, wrong parameter\n"); + return 0; + } + +@@ -1715,7 +1753,7 @@ uint32_t lgw_time_on_air(struct lgw_pkt_tx_s *packet) { + if (val != -1) { + BW = (uint16_t)(val / 1E3); + } else { +- DEBUG_PRINTF("ERROR: Cannot compute time on air for this packet, unsupported bandwidth (0x%02X)\n", packet->bandwidth); ++ ERROR_PRINTF("Cannot compute time on air for this packet, unsupported bandwidth (0x%02X)\n", packet->bandwidth); + return 0; + } + +@@ -1724,7 +1762,7 @@ uint32_t lgw_time_on_air(struct lgw_pkt_tx_s *packet) { + if (val != -1) { + SF = (uint8_t)val; + } else { +- DEBUG_PRINTF("ERROR: Cannot compute time on air for this packet, unsupported datarate (0x%02X)\n", packet->datarate); ++ ERROR_PRINTF("Cannot compute time on air for this packet, unsupported datarate (0x%02X)\n", packet->datarate); + return 0; + } + +@@ -1758,7 +1796,7 @@ uint32_t lgw_time_on_air(struct lgw_pkt_tx_s *packet) { + Tpacket = (uint32_t)Tfsk + 1; /* add margin for rounding */ + } else { + Tpacket = 0; +- DEBUG_PRINTF("ERROR: Cannot compute time on air for this packet, unsupported modulation (0x%02X)\n", packet->modulation); ++ ERROR_PRINTF("Cannot compute time on air for this packet, unsupported modulation (0x%02X)\n", packet->modulation); + } + + return Tpacket; +diff --git a/libloragw/src/loragw_lbt.c b/libloragw/src/loragw_lbt.c +index 9c43521..515e9ac 100644 +--- a/libloragw/src/loragw_lbt.c ++++ b/libloragw/src/loragw_lbt.c +@@ -41,6 +41,8 @@ Maintainer: Michael Coracin + #define CHECK_NULL(a) if(a==NULL){return LGW_REG_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + #define LBT_TIMESTAMP_MASK 0x007FF000 /* 11-bits timestamp */ + + /* -------------------------------------------------------------------------- */ +@@ -326,7 +328,7 @@ int lbt_is_channel_free(struct lgw_pkt_tx_s * pkt_data, uint16_t tx_start_delay, + delta_time = tx_end_time - lbt_time; + } else { + /* It means LBT counter has wrapped */ +- printf("LBT: lbt counter has wrapped\n"); ++ DEBUG_PRINTF("LBT: lbt counter has wrapped\n"); + delta_time = (LBT_TIMESTAMP_MASK - lbt_time) + tx_end_time; + } + +diff --git a/libloragw/src/loragw_radio.c b/libloragw/src/loragw_radio.c +index b3046a9..a01f65b 100644 +--- a/libloragw/src/loragw_radio.c ++++ b/libloragw/src/loragw_radio.c +@@ -46,6 +46,8 @@ Maintainer: Michael Coracin + #define CHECK_NULL(a) if(a==NULL){return LGW_REG_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE TYPES -------------------------------------------------------- */ + +diff --git a/libloragw/src/loragw_reg.c b/libloragw/src/loragw_reg.c +index 14e23cd..6d8aab3 100644 +--- a/libloragw/src/loragw_reg.c ++++ b/libloragw/src/loragw_reg.c +@@ -42,6 +42,8 @@ Maintainer: Sylvain Miermont + #define CHECK_NULL(a) if(a==NULL){return LGW_REG_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + diff --git a/libloragw/src/loragw_spi.native.c b/libloragw/src/loragw_spi.native.c -index c01ed1c..0e2b64c 100644 +index c01ed1c..7cc7eea 100644 --- a/libloragw/src/loragw_spi.native.c +++ b/libloragw/src/loragw_spi.native.c -@@ -54,7 +54,7 @@ Maintainer: Sylvain Miermont +@@ -48,13 +48,15 @@ Maintainer: Sylvain Miermont + #define CHECK_NULL(a) if(a==NULL){return LGW_SPI_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + #define READ_ACCESS 0x00 #define WRITE_ACCESS 0x80 - #define SPI_SPEED 8000000 +-#define SPI_SPEED 8000000 -#define SPI_DEV_PATH "/dev/spidev0.0" ++#define SPI_SPEED (getenv("LORAGW_SPI_SPEED")==NULL ? 8000000 : atoi(getenv("LORAGW_SPI_SPEED"))) +#define SPI_DEV_PATH (getenv("LORAGW_SPI")==NULL ? "/dev/spidev0.0" : getenv("LORAGW_SPI")) //#define SPI_DEV_PATH "/dev/spidev32766.0" - + /* -------------------------------------------------------------------------- */ +@@ -96,6 +98,7 @@ int lgw_spi_open(void **spi_target_ptr) { + } + + /* setting SPI max clk (in Hz) */ ++ INFO_PRINTF("Setting SPI speed to %u\n", SPI_SPEED); + i = SPI_SPEED; + a = ioctl(dev, SPI_IOC_WR_MAX_SPEED_HZ, &i); + b = ioctl(dev, SPI_IOC_RD_MAX_SPEED_HZ, &i); +@@ -111,7 +114,7 @@ int lgw_spi_open(void **spi_target_ptr) { + 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"); ++ ERROR_PRINTF("SPI PORT FAIL TO SET MSB FIRST\n"); + close(dev); + free(spi_device); + return LGW_SPI_ERROR; +@@ -122,14 +125,14 @@ int lgw_spi_open(void **spi_target_ptr) { + 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"); ++ ERROR_PRINTF("SPI PORT FAIL TO SET 8 BITS-PER-WORD\n"); + close(dev); + return LGW_SPI_ERROR; + } + + *spi_device = dev; + *spi_target_ptr = (void *)spi_device; +- DEBUG_MSG("Note: SPI port opened and configured ok\n"); ++ INFO_PRINTF("Note: SPI port opened and configured ok\n"); + return LGW_SPI_SUCCESS; + } + +@@ -150,10 +153,10 @@ int lgw_spi_close(void *spi_target) { + + /* determine return code */ + if (a < 0) { +- DEBUG_MSG("ERROR: SPI PORT FAILED TO CLOSE\n"); ++ ERROR_PRINTF("SPI PORT FAILED TO CLOSE\n"); + return LGW_SPI_ERROR; + } else { +- DEBUG_MSG("Note: SPI port closed\n"); ++ INFO_PRINTF("Note: SPI port closed\n"); + return LGW_SPI_SUCCESS; + } + } +@@ -199,7 +202,7 @@ int lgw_spi_w(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, ui + + /* determine return code */ + if (a != (int)k.len) { +- DEBUG_MSG("ERROR: SPI WRITE FAILURE\n"); ++ ERROR_PRINTF("SPI WRITE FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI write success\n"); +@@ -249,7 +252,7 @@ int lgw_spi_r(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, ui + + /* determine return code */ + if (a != (int)k.len) { +- DEBUG_MSG("ERROR: SPI READ FAILURE\n"); ++ ERROR_PRINTF("SPI READ FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI read success\n"); +@@ -277,7 +280,7 @@ int lgw_spi_wb(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, u + } + CHECK_NULL(data); + if (size == 0) { +- DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); ++ ERROR_PRINTF("BURST OF NULL LENGTH\n"); + return LGW_SPI_ERROR; + } + +@@ -312,7 +315,7 @@ int lgw_spi_wb(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, u + + /* determine return code */ + if (byte_transfered != size) { +- DEBUG_MSG("ERROR: SPI BURST WRITE FAILURE\n"); ++ ERROR_PRINTF("SPI BURST WRITE FAILURE\n"); + return LGW_SPI_ERROR; + } else { + DEBUG_MSG("Note: SPI burst write success\n"); +@@ -339,7 +342,7 @@ int lgw_spi_rb(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, u + } + CHECK_NULL(data); + if (size == 0) { +- DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); ++ ERROR_PRINTF("ERROR: BURST OF NULL LENGTH\n"); + return LGW_SPI_ERROR; + } + +@@ -368,16 +371,16 @@ int lgw_spi_rb(void *spi_target, uint8_t spi_mux_mode, uint8_t spi_mux_target, u + k[1].rx_buf = (unsigned long)(data + offset); + k[1].len = chunk_size; + byte_transfered += (ioctl(spi_device, SPI_IOC_MESSAGE(2), &k) - k[0].len ); +- DEBUG_PRINTF("BURST READ: to trans %d # chunk %d # transferred %d \n", size_to_do, chunk_size, byte_transfered); ++ // 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"); ++ ERROR_PRINTF("ERROR: SPI BURST READ FAILURE\n"); + return LGW_SPI_ERROR; + } else { +- DEBUG_MSG("Note: SPI burst read success\n"); ++ // DEBUG_MSG("Note: SPI burst read success\n"); + return LGW_SPI_SUCCESS; + } + } diff --git a/deps/lgw1302/V1.0.5-corecell.patch b/deps/lgw1302/V1.0.5-corecell.patch deleted file mode 100644 index 27caa24..0000000 --- a/deps/lgw1302/V1.0.5-corecell.patch +++ /dev/null @@ -1,300 +0,0 @@ -diff --git a/libloragw/Makefile b/libloragw/Makefile -index 262167a..45b7444 100644 ---- a/libloragw/Makefile -+++ b/libloragw/Makefile -@@ -12,6 +12,7 @@ CC := $(CROSS_COMPILE)gcc - AR := $(CROSS_COMPILE)ar - - CFLAGS := -O2 -Wall -Wextra -std=c99 -Iinc -I. -I../libtools/inc -+CFLAGS += -DNODEBUG - - OBJDIR = obj - INCLUDES = $(wildcard inc/*.h) $(wildcard ../libtools/inc/*.h) -diff --git a/libloragw/inc/loragw_sx1302_timestamp.h b/libloragw/inc/loragw_sx1302_timestamp.h -index aa6635b..8e5c308 100644 ---- a/libloragw/inc/loragw_sx1302_timestamp.h -+++ b/libloragw/inc/loragw_sx1302_timestamp.h -@@ -43,13 +43,12 @@ License: Revised BSD License, see LICENSE.TXT file include in the project - @struct timestamp_counter_s - @brief context to maintain the internal counters (inst and pps trig) rollover status - */ --struct timestamp_info_s { -- uint32_t counter_us_27bits_ref; /* reference value (last read) */ -- uint8_t counter_us_27bits_wrap; /* rollover/wrap status */ --}; - typedef struct timestamp_counter_s { -- struct timestamp_info_s inst; /* holds current reference of the instantaneous counter */ -- struct timestamp_info_s pps; /* holds current reference of the pps-trigged counter */ -+ struct timestamp_info_s { -+ uint32_t counter_subus; -+ int32_t epochs_subus; -+ int64_t clmono_ref; -+ } inst, pps; - } timestamp_counter_t; - - /* -------------------------------------------------------------------------- */ -@@ -73,27 +72,19 @@ void timestamp_counter_delete(timestamp_counter_t * self); - @brief Update the counter wrapping status based on given current counter - @param self Pointer to the counter handler - @param pps Set to true to update the PPS trig counter status --@param cnt Current value of the counter to be used for the update -+@param cnt Current value of the sub microsecond counter to be used for the update - @return N/A - */ - void timestamp_counter_update(timestamp_counter_t * self, bool pps, uint32_t cnt); - - /** --@brief Convert the 27-bits counter given by the SX1302 to a 32-bits counter which wraps on a uint32_t. --@param self Pointer to the counter handler --@param pps Set to true to expand the counter based on the PPS trig wrapping status --@param cnt_us The 27-bits counter to be expanded --@return the 32-bits counter --*/ --uint32_t timestamp_counter_expand(timestamp_counter_t * self, bool pps, uint32_t cnt_us); -- --/** --@brief Convert the 27-bits packet timestamp to a 32-bits counter which wraps on a uint32_t. --@param self Pointer to the counter handler --@param cnt_us The packet 27-bits counter to be expanded --@return the 32-bits counter -+@brief Convert the 32-bits sub-microsecond counter given by the SX1302 to a 32-bits microsecond counter. -+@param self Pointer to the counter state -+@param pps Set to true to expand the counter based on the PPS trig wrapping status -+@param cnt_subus The 32-bits sub microsecond counter to be converted -+@return the 32-bits microsecond counter - */ --uint32_t timestamp_pkt_expand(timestamp_counter_t * self, uint32_t cnt_us); -+uint32_t timestamp_counter_expand(timestamp_counter_t * self, bool pps, uint32_t cnt_subus); - - /** - @brief Reads the SX1302 internal counter register, and return the 32-bits 1 MHz counter -diff --git a/libloragw/src/loragw_debug.c b/libloragw/src/loragw_debug.c -index 2415d80..2151332 100644 ---- a/libloragw/src/loragw_debug.c -+++ b/libloragw/src/loragw_debug.c -@@ -29,6 +29,15 @@ License: Revised BSD License, see LICENSE.TXT file include in the project - - #include "tinymt32.h" - -+ -+#if defined(NODEBUG) -+void dbg_init_random(void) {} -+void dbg_init_gpio(void) {} -+void dbg_log_buffer_to_file(FILE * file, uint8_t * buffer, uint16_t size) { (void) file; (void) buffer; (void) size; } -+void dbg_log_payload_diff_to_file(FILE * file, uint8_t * buffer1, uint8_t * buffer2, uint16_t size) { (void) file; (void) buffer1; (void) buffer2; (void) size; } -+int dbg_check_payload(struct lgw_conf_debug_s * context, FILE * file, uint8_t * payload_received, uint8_t size, uint8_t ref_payload_idx, uint8_t sf) {(void) context; (void) file; (void) payload_received; (void) size; (void) ref_payload_idx; (void) sf; return 0;} -+#else -+ - /* -------------------------------------------------------------------------- */ - /* --- DEBUG CONSTANTS ------------------------------------------------------ */ - -@@ -199,3 +208,4 @@ int dbg_check_payload(struct lgw_conf_debug_s * context, FILE * file, uint8_t * - - return 0; /* ignored */ - } -+#endif -diff --git a/libloragw/src/loragw_sx1302.c b/libloragw/src/loragw_sx1302.c -index 251fb36..6e1ce4d 100644 ---- a/libloragw/src/loragw_sx1302.c -+++ b/libloragw/src/loragw_sx1302.c -@@ -1812,17 +1812,24 @@ int sx1302_parse(lgw_context_t * context, struct lgw_pkt_rx_s * p) { - timestamp_correction = 0; - } - -- /* Update counter reference / wrap status before expanding */ -- timestamp_counter_get(&counter_us, false); -+ /* Convert sub-us value into micros and do correction */ -+ p->count_us = timestamp_counter_expand(&counter_us, false, pkt.timestamp_cnt) - timestamp_correction; - -- /* Scale 32 MHz packet timestamp to 1 MHz (microseconds) */ -- p->count_us = pkt.timestamp_cnt / 32; -- -- /* Expand 27-bits counter to 32-bits counter, based on current wrapping status */ -- p->count_us = timestamp_pkt_expand(&counter_us, p->count_us); -- -- /* Packet timestamp corrected */ -- p->count_us = p->count_us - timestamp_correction; -+#if 0 // debug code to check for failed submicros/micros handling -+ { -+ static uint32_t last_valid = 0; -+ static uint32_t last_us32 = 0; -+ int32_t diff = p->count_us - last_us32; -+ printf("XXXXXXXXXXXXXXXX pkt=%08X last=%08X diff=%08X/%d seqno=%04X\n", -+ p->count_us, last_us32, diff, diff, (p->payload[1]<<8)|p->payload[2]); -+ if( last_valid && diff > 30000000 ) { -+ printf("XXXXXXXXXXXXXXXX ERROR jump ahead count_us\n"); -+ exit(1); -+ } -+ last_us32 = p->count_us; -+ last_valid = 1; -+ } -+#endif - - /* Packet CRC status */ - p->crc = pkt.rx_crc16_value; -diff --git a/libloragw/src/loragw_sx1302_timestamp.c b/libloragw/src/loragw_sx1302_timestamp.c -index 77c3d4d..487283f 100644 ---- a/libloragw/src/loragw_sx1302_timestamp.c -+++ b/libloragw/src/loragw_sx1302_timestamp.c -@@ -21,9 +21,11 @@ License: Revised BSD License, see LICENSE.TXT file include in the project - /* -------------------------------------------------------------------------- */ - /* --- DEPENDANCIES --------------------------------------------------------- */ - -+#define _POSIX_C_SOURCE 199309L - #include /* C99 types */ - #include /* printf fprintf */ - #include /* memset */ -+#include /* clock monotonic */ - - #include "loragw_sx1302_timestamp.h" - #include "loragw_reg.h" -@@ -62,6 +64,16 @@ License: Revised BSD License, see LICENSE.TXT file include in the project - /* -------------------------------------------------------------------------- */ - /* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */ - -+static int64_t clock_monotonic() { -+ struct timespec ts; -+ if( clock_gettime(CLOCK_MONOTONIC, &ts) != 0 ) { -+ printf("ERROR: clock_gettime(CLOCK_MONOTONIC, ..) failed!\n"); -+ return 0; -+ } -+ /* Return subus resolution - rounded, +1 makes sure 0 is never returned */ -+ return ((ts.tv_sec+1)*1000000000LL + ts.tv_nsec + 16) / 32; -+} -+ - /* -------------------------------------------------------------------------- */ - /* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ - -@@ -77,17 +89,36 @@ void timestamp_counter_delete(timestamp_counter_t * self) { - - /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - --void timestamp_counter_update(timestamp_counter_t * self, bool pps, uint32_t cnt) { -- struct timestamp_info_s* tinfo = (pps == true) ? &self->pps : &self->inst; -- -- /* Check if counter has wrapped, and update wrap status if necessary */ -- if (cnt < tinfo->counter_us_27bits_ref) { -- tinfo->counter_us_27bits_wrap += 1; -- tinfo->counter_us_27bits_wrap %= 32; -+void timestamp_counter_update(timestamp_counter_t * self, bool pps, uint32_t cnt_subus) { -+ struct timestamp_info_s* tinfo = pps ? &self->pps : &self->inst; -+ int64_t now = clock_monotonic(); -+ if( tinfo->clmono_ref == 0 ) { -+ tinfo->clmono_ref = now; -+ tinfo->counter_subus = cnt_subus; -+ return; - } -- -- /* Update counter reference */ -- tinfo->counter_us_27bits_ref = cnt; -+ /* -+ * Let m1,m2 be previous/current clock monotonic (64bit) -+ * and u1,u2 corresponding 32bit submicrosecond recordings from SX1302 -+ * There are the following errors to consider: -+ * e1 = (int32_t)(m1-u1) -+ * e2 = (int32_t)(m2-u2) -+ * e1,e2 are related to local CPU processing jitter since the time between clock_monotonic() and -+ * the retrieval of the submicrosecond counter varies due to processing overhead. -+ * e3 = (int2_t)((uint32_t)(u2-u1) - (uint32_t)(m2-m2)) -+ * e3 is the CPU clock drift against the submicrosecond counter. -+ * E=e1+e2+e3 is significantly smaller than 2^31 submicroseconds (<<<~67s) -+ * The assumption is that the submicrosecond counter may have rolled over possibly multiple times -+ * betwen calls to timestamp_counter_update(). -+ * Thus: -+ * m2-m1 = k*2^32 + (uint32_t)(u2-u1) + E -+ * and the number of rollovers is calculated as: -+ * k*2^32 = (m2-m1) - (uint32_t)(u2-u1) - E and -2^31 <<< E <<< 2^31 -+ */ -+ int64_t diff = now - tinfo->clmono_ref - (uint32_t)(cnt_subus - tinfo->counter_subus); -+ tinfo->epochs_subus += ((diff + (1U<<31)) >> 32) + (cnt_subus < tinfo->counter_subus ? 1:0); -+ tinfo->counter_subus = cnt_subus; -+ tinfo->clmono_ref = now; - } - - /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -@@ -95,7 +126,7 @@ void timestamp_counter_update(timestamp_counter_t * self, bool pps, uint32_t cnt - uint32_t timestamp_counter_get(timestamp_counter_t * self, bool pps) { - int x; - uint8_t buff[4]; -- uint32_t counter_us_raw_27bits_now; -+ uint32_t counter_subus; - int32_t msb; - - /* Get the 32MHz timestamp counter - 4 bytes */ -@@ -128,25 +159,22 @@ uint32_t timestamp_counter_get(timestamp_counter_t * self, bool pps) { - } - } - -- counter_us_raw_27bits_now = (buff[0]<<24) | (buff[1]<<16) | (buff[2]<<8) | buff[3]; -- -- /* Scale to 1MHz */ -- counter_us_raw_27bits_now /= 32; -+ counter_subus = (buff[0]<<24) | (buff[1]<<16) | (buff[2]<<8) | buff[3]; - - /* Update counter wrapping status */ -- timestamp_counter_update(self, pps, counter_us_raw_27bits_now); -+ timestamp_counter_update(self, pps, counter_subus); - -- /* Convert 27-bits counter to 32-bits counter */ -- return timestamp_counter_expand(self, pps, counter_us_raw_27bits_now); -+ /* Convert 1/32 microsecond to microsecond counter */ -+ return timestamp_counter_expand(self, pps, counter_subus); - } - - /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - --uint32_t timestamp_counter_expand(timestamp_counter_t * self, bool pps, uint32_t cnt_us) { -+uint32_t timestamp_counter_expand(timestamp_counter_t * self, bool pps, uint32_t cnt_subus) { - struct timestamp_info_s* tinfo = (pps == true) ? &self->pps : &self->inst; -- uint32_t counter_us_32bits; -- -- counter_us_32bits = (tinfo->counter_us_27bits_wrap << 27) | cnt_us; -+ /* Convert submicroseconds (1/32us = 31.25ns) into microseconds */ -+ int32_t delta_subus = (int32_t)(cnt_subus - tinfo->counter_subus); /* this *must* be a 32bit signed value */ -+ uint32_t counter_us_32bits = (((int64_t)tinfo->epochs_subus << 32) + tinfo->counter_subus + delta_subus) >> 5; - - #if 0 - /* DEBUG: to be enabled when running test_loragw_counter test application -@@ -154,41 +182,13 @@ uint32_t timestamp_counter_expand(timestamp_counter_t * self, bool pps, uint32_t - > set datafile separator comma - > plot for [col=1:2:1] 'log_count.txt' using col with lines - */ -- printf("%u,%u,%u\n", cnt_us, counter_us_32bits, tinfo->counter_us_27bits_wrap); -+ printf("%u,%u,%llu\n", cnt_subus, counter_us_32bits, tinfo->counter_subus); - #endif - - return counter_us_32bits; - } - - --/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -- --uint32_t timestamp_pkt_expand(timestamp_counter_t * self, uint32_t pkt_cnt_us) { -- struct timestamp_info_s* tinfo = &self->inst; -- uint32_t counter_us_32bits; -- uint8_t wrap_status; -- -- /* Check if counter has wrapped since the packet has been received in the sx1302 internal FIFO */ -- /* If the sx1302 counter was greater than the pkt timestamp, it means that the internal counter -- hasn't rolled over since the packet has been received by the sx1302 -- case 1: --|-P--|----|--R-|----|--||-|----|-- : use current wrap status counter -- case 2: --|-P-||-|-R--|-- : use previous wrap status counter -- P : packet received in sx1302 internal FIFO -- R : read packet from sx1302 internal FIFO -- | : last update internal counter ref value. -- ||: sx1302 internal counter rollover (wrap) -- */ -- -- /* Use current wrap counter or previous ? */ -- wrap_status = tinfo->counter_us_27bits_wrap - ((tinfo->counter_us_27bits_ref >= pkt_cnt_us) ? 0 : 1); -- wrap_status &= 0x1F; /* [0..31] */ -- -- /* Expand packet counter */ -- counter_us_32bits = (wrap_status << 27) | pkt_cnt_us; -- -- return counter_us_32bits; --} -- - /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - - int timestamp_counter_mode(bool enable_precision_ts, uint8_t max_ts_metrics, uint8_t nb_symbols) { diff --git a/deps/lgw1302/V2.1.0-corecell.patch b/deps/lgw1302/V2.1.0-corecell.patch new file mode 100644 index 0000000..f212880 --- /dev/null +++ b/deps/lgw1302/V2.1.0-corecell.patch @@ -0,0 +1,2827 @@ +diff --git a/libloragw/Makefile b/libloragw/Makefile +index 881442f..425bb48 100644 +--- a/libloragw/Makefile ++++ b/libloragw/Makefile +@@ -12,6 +12,7 @@ CC := $(CROSS_COMPILE)gcc + AR := $(CROSS_COMPILE)ar + + CFLAGS := -O2 -Wall -Wextra -std=c99 -Iinc -I. -I../libtools/inc ++CFLAGS += ${EXTRA_CFLAGS} + + OBJDIR = obj + INCLUDES = $(wildcard inc/*.h) $(wildcard ../libtools/inc/*.h) +diff --git a/libloragw/inc/loragw_hal.h b/libloragw/inc/loragw_hal.h +index 6e153a3..45981b5 100644 +--- a/libloragw/inc/loragw_hal.h ++++ b/libloragw/inc/loragw_hal.h +@@ -45,6 +45,7 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + #define LGW_HAL_SUCCESS 0 + #define LGW_HAL_ERROR -1 + #define LGW_LBT_NOT_ALLOWED 1 ++#define LGW_LBT_ISSUE 1 + + /* radio-specific parameters */ + #define LGW_XTAL_FREQU 32000000 /* frequency of the RF reference oscillator */ +diff --git a/libloragw/inc/loragw_spi.h b/libloragw/inc/loragw_spi.h +index 88e4530..1b83698 100644 +--- a/libloragw/inc/loragw_spi.h ++++ b/libloragw/inc/loragw_spi.h +@@ -23,6 +23,7 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + /* --- DEPENDANCIES --------------------------------------------------------- */ + + #include /* C99 types*/ ++#include /* getenv atoi */ + + #include "config.h" /* library configuration options (dynamically generated) */ + +@@ -32,7 +33,7 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + #define LGW_SPI_SUCCESS 0 + #define LGW_SPI_ERROR -1 + +-#define SPI_SPEED 2000000 ++#define SPI_SPEED (getenv("LORAGW_SPI_SPEED")==NULL ? 2000000 : atoi(getenv("LORAGW_SPI_SPEED"))) + + /* -------------------------------------------------------------------------- */ + /* --- PUBLIC FUNCTIONS PROTOTYPES ------------------------------------------ */ +diff --git a/libloragw/inc/loragw_stationlog.h b/libloragw/inc/loragw_stationlog.h +new file mode 100644 +index 0000000..a282b8f +--- /dev/null ++++ b/libloragw/inc/loragw_stationlog.h +@@ -0,0 +1,26 @@ ++#ifndef _LORAGW_STATIONLOG_H ++#define _LORAGW_STATIONLOG_H ++ ++#if defined(STATIONLOG) ++ ++#undef DEBUG_PRINTF ++#undef DEBUG_MSG ++ ++enum { XDEBUG=0, DEBUG, VERBOSE, INFO, NOTICE, WARNING, ERROR, CRITICAL }; ++extern void log_hal (uint8_t level, const char* fmt, ...); ++#define ERROR_PRINTF(fmt, ...) log_hal(ERROR , "[%s:%d] "fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__) ++#define INFO_PRINTF(fmt, ...) log_hal(INFO , "[%s:%d] "fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__) ++#define DEBUG_PRINTF(fmt, ...) log_hal(XDEBUG , "[%s:%d] "fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__) ++#define DEBUG_MSG(str) log_hal(XDEBUG , "[%s:%d] %s", __FUNCTION__, __LINE__, str) ++#define XDEBUG_PRINTF(fmt, ...) log_hal(XDEBUG , "[%s:%d] "fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__) ++#define XDEBUG_MSG(str) log_hal(XDEBUG , "[%s:%d] %s", __FUNCTION__, __LINE__, str) ++ ++#else // !defined(STATIONLOG) ++ ++#define ERROR_PRINTF(fmt, ...) DEBUG_PRINTF(fmt, ## __VA_ARGS__) ++#define INFO_PRINTF(fmt, ...) DEBUG_PRINTF(fmt, ## __VA_ARGS__) ++#define XDEBUG_PRINTF(fmt, ...) DEBUG_PRINTF(fmt, ## __VA_ARGS__) ++#define XDEBUG_MSG(str) DEBUG_MSG(str) ++#endif ++ ++#endif +diff --git a/libloragw/src/loragw_ad5338r.c b/libloragw/src/loragw_ad5338r.c +index ea08513..6d1118c 100644 +--- a/libloragw/src/loragw_ad5338r.c ++++ b/libloragw/src/loragw_ad5338r.c +@@ -32,6 +32,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + #define CHECK_NULL(a) if(a==NULL){return LGW_I2C_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */ + +diff --git a/libloragw/src/loragw_cal.c b/libloragw/src/loragw_cal.c +index a3cfe2d..2644e7d 100644 +--- a/libloragw/src/loragw_cal.c ++++ b/libloragw/src/loragw_cal.c +@@ -46,6 +46,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + #define CHECK_NULL(a) if(a==NULL){return LGW_SPI_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + +diff --git a/libloragw/src/loragw_com.c b/libloragw/src/loragw_com.c +index d6a0894..64c4c98 100644 +--- a/libloragw/src/loragw_com.c ++++ b/libloragw/src/loragw_com.c +@@ -40,6 +40,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + #define CHECK_NULL(a) if(a==NULL){return LGW_COM_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + +@@ -65,7 +67,7 @@ int lgw_com_open(lgw_com_type_t com_type, const char * com_path) { + /* Check input parameters */ + CHECK_NULL(com_path); + if ((com_type != LGW_COM_SPI) && (com_type != LGW_COM_USB)) { +- DEBUG_MSG("ERROR: COMMUNICATION INTERFACE TYPE IS NOT SUPPORTED\n"); ++ ERROR_PRINTF("COMMUNICATION INTERFACE TYPE IS NOT SUPPORTED\n"); + return LGW_COM_ERROR; + } + +@@ -79,11 +81,11 @@ int lgw_com_open(lgw_com_type_t com_type, const char * com_path) { + + switch (com_type) { + case LGW_COM_SPI: +- printf("Opening SPI communication interface\n"); ++ INFO_PRINTF("Opening SPI communication interface\n"); + com_stat = lgw_spi_open(com_path, &_lgw_com_target); + break; + case LGW_COM_USB: +- printf("Opening USB communication interface\n"); ++ INFO_PRINTF("Opening USB communication interface\n"); + com_stat = lgw_usb_open(com_path, &_lgw_com_target); + break; + default: +@@ -101,21 +103,21 @@ int lgw_com_close(void) { + int com_stat; + + if (_lgw_com_target == NULL) { +- printf("ERROR: concentrator is not connected\n"); ++ ERROR_PRINTF("concentrator is not connected\n"); + return -1; + } + + switch (_lgw_com_type) { + case LGW_COM_SPI: +- printf("Closing SPI communication interface\n"); ++ INFO_PRINTF("Closing SPI communication interface\n"); + com_stat = lgw_spi_close(_lgw_com_target); + break; + case LGW_COM_USB: +- printf("Closing USB communication interface\n"); ++ INFO_PRINTF("Closing USB communication interface\n"); + com_stat = lgw_usb_close(_lgw_com_target); + break; + default: +- printf("ERROR(%s:%d): wrong communication type (SHOULD NOT HAPPEN)\n", __FUNCTION__, __LINE__); ++ ERROR_PRINTF("wrong communication type (SHOULD NOT HAPPEN)\n"); + com_stat = LGW_COM_ERROR; + break; + } +@@ -147,7 +149,7 @@ int lgw_com_w(uint8_t spi_mux_target, uint16_t address, uint8_t data) { + com_stat = lgw_usb_w(_lgw_com_target, spi_mux_target, address, data); + break; + default: +- printf("ERROR(%s:%d): wrong communication type (SHOULD NOT HAPPEN)\n", __FUNCTION__, __LINE__); ++ ERROR_PRINTF("wrong communication type (SHOULD NOT HAPPEN)\n"); + com_stat = LGW_COM_ERROR; + break; + } +@@ -181,7 +183,7 @@ int lgw_com_r(uint8_t spi_mux_target, uint16_t address, uint8_t *data) { + com_stat = lgw_usb_r(_lgw_com_target, spi_mux_target, address, data); + break; + default: +- printf("ERROR(%s:%d): wrong communication type (SHOULD NOT HAPPEN)\n", __FUNCTION__, __LINE__); ++ ERROR_PRINTF("wrong communication type (SHOULD NOT HAPPEN)\n"); + com_stat = LGW_COM_ERROR; + break; + } +@@ -213,7 +215,7 @@ int lgw_com_rmw(uint8_t spi_mux_target, uint16_t address, uint8_t offs, uint8_t + com_stat = lgw_usb_rmw(_lgw_com_target, address, offs, leng, data); + break; + default: +- printf("ERROR(%s:%d): wrong communication type (SHOULD NOT HAPPEN)\n", __FUNCTION__, __LINE__); ++ ERROR_PRINTF("wrong communication type (SHOULD NOT HAPPEN)\n"); + com_stat = LGW_COM_ERROR; + break; + } +@@ -247,7 +249,7 @@ int lgw_com_wb(uint8_t spi_mux_target, uint16_t address, const uint8_t *data, ui + com_stat = lgw_usb_wb(_lgw_com_target, spi_mux_target, address, data, size); + break; + default: +- printf("ERROR(%s:%d): wrong communication type (SHOULD NOT HAPPEN)\n", __FUNCTION__, __LINE__); ++ ERROR_PRINTF("wrong communication type (SHOULD NOT HAPPEN)\n"); + com_stat = LGW_COM_ERROR; + break; + } +@@ -281,7 +283,7 @@ int lgw_com_rb(uint8_t spi_mux_target, uint16_t address, uint8_t *data, uint16_t + com_stat = lgw_usb_rb(_lgw_com_target, spi_mux_target, address, data, size); + break; + default: +- printf("ERROR(%s:%d): wrong communication type (SHOULD NOT HAPPEN)\n", __FUNCTION__, __LINE__); ++ ERROR_PRINTF("wrong communication type (SHOULD NOT HAPPEN)\n"); + com_stat = LGW_COM_ERROR; + break; + } +@@ -305,7 +307,7 @@ int lgw_com_set_write_mode(lgw_com_write_mode_t write_mode) { + com_stat = lgw_usb_set_write_mode(write_mode); + break; + default: +- printf("ERROR(%s:%d): wrong communication type (SHOULD NOT HAPPEN)\n", __FUNCTION__, __LINE__); ++ ERROR_PRINTF("wrong communication type (SHOULD NOT HAPPEN)\n"); + com_stat = LGW_COM_ERROR; + break; + } +@@ -326,7 +328,7 @@ int lgw_com_flush(void) { + com_stat = lgw_usb_flush(_lgw_com_target); + break; + default: +- printf("ERROR(%s:%d): wrong communication type (SHOULD NOT HAPPEN)\n", __FUNCTION__, __LINE__); ++ ERROR_PRINTF("wrong communication type (SHOULD NOT HAPPEN)\n"); + com_stat = LGW_COM_ERROR; + break; + } +@@ -344,7 +346,7 @@ uint16_t lgw_com_chunk_size(void) { + return lgw_usb_chunk_size(); + break; + default: +- printf("ERROR(%s:%d): wrong communication type (SHOULD NOT HAPPEN)\n", __FUNCTION__, __LINE__); ++ ERROR_PRINTF("wrong communication type (SHOULD NOT HAPPEN)\n"); + return 0; + } + } +@@ -358,12 +360,12 @@ int lgw_com_get_temperature(float * temperature) { + + switch (_lgw_com_type) { + case LGW_COM_SPI: +- printf("ERROR(%s:%d): not supported for SPI com\n", __FUNCTION__, __LINE__); ++ ERROR_PRINTF("not supported for SPI com\n"); + return -1; + case LGW_COM_USB: + return lgw_usb_get_temperature(_lgw_com_target, temperature); + default: +- printf("ERROR(%s:%d): wrong communication type (SHOULD NOT HAPPEN)\n", __FUNCTION__, __LINE__); ++ ERROR_PRINTF("wrong communication type (SHOULD NOT HAPPEN)\n"); + return LGW_COM_ERROR; + } + } +diff --git a/libloragw/src/loragw_debug.c b/libloragw/src/loragw_debug.c +index 9a81a08..2314e32 100644 +--- a/libloragw/src/loragw_debug.c ++++ b/libloragw/src/loragw_debug.c +@@ -27,6 +27,14 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + #include "loragw_hal.h" + #include "loragw_debug.h" + ++#if defined(NODEBUG) ++void dbg_init_random(void) {} ++void dbg_init_gpio(void) {} ++void dbg_log_buffer_to_file(FILE * file, uint8_t * buffer, uint16_t size) { (void) file; (void) buffer; (void) size; } ++void dbg_log_payload_diff_to_file(FILE * file, uint8_t * buffer1, uint8_t * buffer2, uint16_t size) { (void) file; (void) buffer1; (void) buffer2; (void) size; } ++int dbg_check_payload(struct lgw_conf_debug_s * context, FILE * file, uint8_t * payload_received, uint8_t size, uint8_t ref_payload_idx, uint8_t sf) {(void) context; (void) file; (void) payload_received; (void) size; (void) ref_payload_idx; (void) sf; return 0;} ++#else ++ + #include "tinymt32.h" + + /* -------------------------------------------------------------------------- */ +@@ -181,3 +189,4 @@ int dbg_check_payload(struct lgw_conf_debug_s * context, FILE * file, uint8_t * + + return 0; /* ignored */ + } ++#endif +diff --git a/libloragw/src/loragw_hal.c b/libloragw/src/loragw_hal.c +index ffc8ec0..60e8387 100644 +--- a/libloragw/src/loragw_hal.c ++++ b/libloragw/src/loragw_hal.c +@@ -69,6 +69,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + #define CHECK_NULL(a) if(a==NULL){return LGW_HAL_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + #define TRACE() fprintf(stderr, "@ %s %d\n", __FUNCTION__, __LINE__); + + #define CONTEXT_STARTED lgw_context.is_started +@@ -277,7 +279,7 @@ static int remove_pkt(struct lgw_pkt_rx_s * p, uint8_t * nb_pkt, uint8_t pkt_ind + CHECK_NULL(p); + CHECK_NULL(nb_pkt); + if (pkt_index > ((*nb_pkt) - 1)) { +- printf("ERROR: failed to remove packet index %u\n", pkt_index); ++ ERROR_PRINTF("failed to remove packet index %u\n", pkt_index); + return -1; + } + +@@ -390,11 +392,13 @@ static int merge_packets(struct lgw_pkt_rx_s * p, uint8_t * nb_pkt) { + } + } + /* pkt_dup_idx contains the index to be deleted */ ++#if DEBUG_HAL == 1 + DEBUG_PRINTF("duplicate found %d:%d, deleting %d\n", pkt_idx, pkt_dup_idx, pkt_dup_idx); ++#endif + /* Remove duplicated packet from packet array */ + x = remove_pkt(p, &cpt, pkt_dup_idx); + if (x != 0) { +- printf("ERROR: failed to remove packet from array (%d)\n", x); ++ ERROR_PRINTF("failed to remove packet from array (%d)\n", x); + } + dup_restart = true; + break; +@@ -453,13 +457,13 @@ int lgw_board_setconf(struct lgw_conf_board_s * conf) { + + /* check if the concentrator is running */ + if (CONTEXT_STARTED == true) { +- DEBUG_MSG("ERROR: CONCENTRATOR IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); ++ ERROR_PRINTF("CONCENTRATOR IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); + return LGW_HAL_ERROR; + } + + /* Check input parameters */ + if ((conf->com_type != LGW_COM_SPI) && (conf->com_type != LGW_COM_USB)) { +- DEBUG_MSG("ERROR: WRONG COM TYPE\n"); ++ ERROR_PRINTF("WRONG COM TYPE\n"); + return LGW_HAL_ERROR; + } + +@@ -487,7 +491,7 @@ int lgw_rxrf_setconf(uint8_t rf_chain, struct lgw_conf_rxrf_s * conf) { + + /* check if the concentrator is running */ + if (CONTEXT_STARTED == true) { +- DEBUG_MSG("ERROR: CONCENTRATOR IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); ++ ERROR_PRINTF("CONCENTRATOR IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); + return LGW_HAL_ERROR; + } + +@@ -499,19 +503,19 @@ int lgw_rxrf_setconf(uint8_t rf_chain, struct lgw_conf_rxrf_s * conf) { + + /* check input range (segfault prevention) */ + if (rf_chain >= LGW_RF_CHAIN_NB) { +- DEBUG_MSG("ERROR: NOT A VALID RF_CHAIN NUMBER\n"); ++ ERROR_PRINTF("NOT A VALID RF_CHAIN NUMBER\n"); + return LGW_HAL_ERROR; + } + + /* check if radio type is supported */ + if ((conf->type != LGW_RADIO_TYPE_SX1255) && (conf->type != LGW_RADIO_TYPE_SX1257) && (conf->type != LGW_RADIO_TYPE_SX1250)) { +- DEBUG_PRINTF("ERROR: NOT A VALID RADIO TYPE (%d)\n", conf->type); ++ ERROR_PRINTF("NOT A VALID RADIO TYPE (%d)\n", conf->type); + return LGW_HAL_ERROR; + } + + /* check if the radio central frequency is valid */ + if ((conf->freq_hz < LGW_RF_RX_FREQ_MIN) || (conf->freq_hz > LGW_RF_RX_FREQ_MAX)) { +- DEBUG_PRINTF("ERROR: NOT A VALID RADIO CENTER FREQUENCY, PLEASE CHECK IF IT HAS BEEN GIVEN IN HZ (%u)\n", conf->freq_hz); ++ ERROR_PRINTF("NOT A VALID RADIO CENTER FREQUENCY, PLEASE CHECK IF IT HAS BEEN GIVEN IN HZ (%u)\n", conf->freq_hz); + return LGW_HAL_ERROR; + } + +@@ -549,13 +553,13 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s * conf) { + + /* check if the concentrator is running */ + if (CONTEXT_STARTED == true) { +- DEBUG_MSG("ERROR: CONCENTRATOR IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); ++ ERROR_PRINTF("CONCENTRATOR IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); + return LGW_HAL_ERROR; + } + + /* check input range (segfault prevention) */ + if (if_chain >= LGW_IF_CHAIN_NB) { +- DEBUG_PRINTF("ERROR: %d NOT A VALID IF_CHAIN NUMBER\n", if_chain); ++ ERROR_PRINTF("%d NOT A VALID IF_CHAIN NUMBER\n", if_chain); + return LGW_HAL_ERROR; + } + +@@ -569,10 +573,10 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s * conf) { + + /* check 'general' parameters */ + if (sx1302_get_ifmod_config(if_chain) == IF_UNDEFINED) { +- DEBUG_PRINTF("ERROR: IF CHAIN %d NOT CONFIGURABLE\n", if_chain); ++ ERROR_PRINTF("IF CHAIN %d NOT CONFIGURABLE\n", if_chain); + } + if (conf->rf_chain >= LGW_RF_CHAIN_NB) { +- DEBUG_MSG("ERROR: INVALID RF_CHAIN TO ASSOCIATE WITH A LORA_STD IF CHAIN\n"); ++ ERROR_PRINTF("INVALID RF_CHAIN TO ASSOCIATE WITH A LORA_STD IF CHAIN\n"); + return LGW_HAL_ERROR; + } + /* check if IF frequency is optimal based on channel and radio bandwidths */ +@@ -590,10 +594,10 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s * conf) { + } + bw_hz = lgw_bw_getval(conf->bandwidth); /* channel bandwidth */ + if ((conf->freq_hz + ((bw_hz==-1)?LGW_REF_BW:bw_hz)/2) > ((int32_t)rf_rx_bandwidth/2)) { +- DEBUG_PRINTF("ERROR: IF FREQUENCY %d TOO HIGH\n", conf->freq_hz); ++ ERROR_PRINTF("IF FREQUENCY %d TOO HIGH\n", conf->freq_hz); + return LGW_HAL_ERROR; + } else if ((conf->freq_hz - ((bw_hz==-1)?LGW_REF_BW:bw_hz)/2) < -((int32_t)rf_rx_bandwidth/2)) { +- DEBUG_PRINTF("ERROR: IF FREQUENCY %d TOO LOW\n", conf->freq_hz); ++ ERROR_PRINTF("IF FREQUENCY %d TOO LOW\n", conf->freq_hz); + return LGW_HAL_ERROR; + } + +@@ -610,11 +614,11 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s * conf) { + } + /* check BW & DR */ + if (!IS_LORA_BW(conf->bandwidth)) { +- DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA_STD IF CHAIN\n"); ++ ERROR_PRINTF("BANDWIDTH NOT SUPPORTED BY LORA_STD IF CHAIN\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_DR(conf->datarate)) { +- DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY LORA_STD IF CHAIN\n"); ++ ERROR_PRINTF("DATARATE NOT SUPPORTED BY LORA_STD IF CHAIN\n"); + return LGW_HAL_ERROR; + } + /* set internal configuration */ +@@ -645,11 +649,11 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s * conf) { + } + /* check BW & DR */ + if (conf->bandwidth != BW_125KHZ) { +- DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); ++ ERROR_PRINTF("BANDWIDTH NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_DR(conf->datarate)) { +- DEBUG_MSG("ERROR: DATARATE(S) NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); ++ ERROR_PRINTF("DATARATE(S) NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); + return LGW_HAL_ERROR; + } + /* set internal configuration */ +@@ -672,11 +676,11 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s * conf) { + } + /* check BW & DR */ + if(!IS_FSK_BW(conf->bandwidth)) { +- DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY FSK IF CHAIN\n"); ++ ERROR_PRINTF("BANDWIDTH NOT SUPPORTED BY FSK IF CHAIN\n"); + return LGW_HAL_ERROR; + } + if(!IS_FSK_DR(conf->datarate)) { +- DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); ++ ERROR_PRINTF("DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); + return LGW_HAL_ERROR; + } + /* set internal configuration */ +@@ -700,7 +704,7 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s * conf) { + break; + + default: +- DEBUG_PRINTF("ERROR: IF CHAIN %d TYPE NOT SUPPORTED\n", if_chain); ++ ERROR_PRINTF("IF CHAIN %d TYPE NOT SUPPORTED\n", if_chain); + return LGW_HAL_ERROR; + } + +@@ -726,7 +730,7 @@ int lgw_txgain_setconf(uint8_t rf_chain, struct lgw_tx_gain_lut_s * conf) { + + /* Check LUT size */ + if ((conf->size < 1) || (conf->size > TX_GAIN_LUT_SIZE_MAX)) { +- DEBUG_PRINTF("ERROR: TX gain LUT must have at least one entry and maximum %d entries\n", TX_GAIN_LUT_SIZE_MAX); ++ ERROR_PRINTF("TX gain LUT must have at least one entry and maximum %d entries\n", TX_GAIN_LUT_SIZE_MAX); + return LGW_HAL_ERROR; + } + +@@ -735,23 +739,23 @@ int lgw_txgain_setconf(uint8_t rf_chain, struct lgw_tx_gain_lut_s * conf) { + for (i = 0; i < CONTEXT_TX_GAIN_LUT[rf_chain].size; i++) { + /* Check gain range */ + if (conf->lut[i].dig_gain > 3) { +- DEBUG_MSG("ERROR: TX gain LUT: SX1302 digital gain must be between 0 and 3\n"); ++ ERROR_PRINTF("TX gain LUT: SX1302 digital gain must be between 0 and 3\n"); + return LGW_HAL_ERROR; + } + if (conf->lut[i].dac_gain > 3) { +- DEBUG_MSG("ERROR: TX gain LUT: SX1257 DAC gains must not exceed 3\n"); ++ ERROR_PRINTF("TX gain LUT: SX1257 DAC gains must not exceed 3\n"); + return LGW_HAL_ERROR; + } + if ((conf->lut[i].mix_gain < 5) || (conf->lut[i].mix_gain > 15)) { +- DEBUG_MSG("ERROR: TX gain LUT: SX1257 mixer gain must be betwen [5..15]\n"); ++ ERROR_PRINTF("TX gain LUT: SX1257 mixer gain must be betwen [5..15]\n"); + return LGW_HAL_ERROR; + } + if (conf->lut[i].pa_gain > 3) { +- DEBUG_MSG("ERROR: TX gain LUT: External PA gain must not exceed 3\n"); ++ ERROR_PRINTF("TX gain LUT: External PA gain must not exceed 3\n"); + return LGW_HAL_ERROR; + } + if (conf->lut[i].pwr_idx > 22) { +- DEBUG_MSG("ERROR: TX gain LUT: SX1250 power index must not exceed 22\n"); ++ ERROR_PRINTF("TX gain LUT: SX1250 power index must not exceed 22\n"); + return LGW_HAL_ERROR; + } + +@@ -802,11 +806,11 @@ int lgw_sx1261_setconf(struct lgw_conf_sx1261_s * conf) { + CONTEXT_SX1261.lbt_conf.nb_channel = conf->lbt_conf.nb_channel; + for (i = 0; i < CONTEXT_SX1261.lbt_conf.nb_channel; i++) { + if (conf->lbt_conf.channels[i].bandwidth != BW_125KHZ && conf->lbt_conf.channels[i].bandwidth != BW_250KHZ) { +- printf("ERROR: bandwidth not supported for LBT channel %d\n", i); ++ ERROR_PRINTF("bandwidth not supported for LBT channel %d\n", i); + return LGW_HAL_ERROR; + } + if (conf->lbt_conf.channels[i].scan_time_us != LGW_LBT_SCAN_TIME_128_US && conf->lbt_conf.channels[i].scan_time_us != LGW_LBT_SCAN_TIME_5000_US) { +- printf("ERROR: scan_time_us not supported for LBT channel %d\n", i); ++ ERROR_PRINTF("scan_time_us not supported for LBT channel %d\n", i); + return LGW_HAL_ERROR; + } + CONTEXT_SX1261.lbt_conf.channels[i] = conf->lbt_conf.channels[i]; +@@ -857,21 +861,21 @@ int lgw_start(void) { + + err = lgw_connect(CONTEXT_COM_TYPE, CONTEXT_COM_PATH); + if (err == LGW_REG_ERROR) { +- DEBUG_MSG("ERROR: FAIL TO CONNECT BOARD\n"); ++ ERROR_PRINTF("FAIL TO CONNECT BOARD\n"); + return LGW_HAL_ERROR; + } + + /* Set all GPIOs to 0 */ + err = sx1302_set_gpio(0x00); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to set all GPIOs to 0\n"); ++ ERROR_PRINTF("failed to set all GPIOs to 0\n"); + return LGW_HAL_ERROR; + } + + /* Calibrate radios */ + err = sx1302_radio_calibrate(&CONTEXT_RF_CHAIN[0], CONTEXT_BOARD.clksrc, &CONTEXT_TX_GAIN_LUT[0]); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: radio calibration failed\n"); ++ ERROR_PRINTF("radio calibration failed\n"); + return LGW_HAL_ERROR; + } + +@@ -881,7 +885,7 @@ int lgw_start(void) { + /* Reset the radio */ + err = sx1302_radio_reset(i, CONTEXT_RF_CHAIN[i].type); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to reset radio %d\n", i); ++ ERROR_PRINTF("failed to reset radio %d\n", i); + return LGW_HAL_ERROR; + } + +@@ -895,18 +899,18 @@ int lgw_start(void) { + err = sx125x_setup(i, CONTEXT_BOARD.clksrc, true, CONTEXT_RF_CHAIN[i].type, CONTEXT_RF_CHAIN[i].freq_hz); + break; + default: +- printf("ERROR: RADIO TYPE NOT SUPPORTED (RF_CHAIN %d)\n", i); ++ ERROR_PRINTF("RADIO TYPE NOT SUPPORTED (RF_CHAIN %d)\n", i); + return LGW_HAL_ERROR; + } + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to setup radio %d\n", i); ++ ERROR_PRINTF("failed to setup radio %d\n", i); + return LGW_HAL_ERROR; + } + + /* Set radio mode */ + err = sx1302_radio_set_mode(i, CONTEXT_RF_CHAIN[i].type); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to set mode for radio %d\n", i); ++ ERROR_PRINTF("failed to set mode for radio %d\n", i); + return LGW_HAL_ERROR; + } + } +@@ -915,54 +919,54 @@ int lgw_start(void) { + /* Select the radio which provides the clock to the sx1302 */ + err = sx1302_radio_clock_select(CONTEXT_BOARD.clksrc); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to get clock from radio %u\n", CONTEXT_BOARD.clksrc); ++ ERROR_PRINTF("failed to get clock from radio %u\n", CONTEXT_BOARD.clksrc); + return LGW_HAL_ERROR; + } + + /* Release host control on radio (will be controlled by AGC) */ + err = sx1302_radio_host_ctrl(false); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to release control over radios\n"); ++ ERROR_PRINTF("failed to release control over radios\n"); + return LGW_HAL_ERROR; + } + + /* Basic initialization of the sx1302 */ + err = sx1302_init(&CONTEXT_FINE_TIMESTAMP); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to initialize SX1302\n"); ++ ERROR_PRINTF("failed to initialize SX1302\n"); + return LGW_HAL_ERROR; + } + + /* Configure PA/LNA LUTs */ + err = sx1302_pa_lna_lut_configure(&CONTEXT_BOARD); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to configure SX1302 PA/LNA LUT\n"); ++ ERROR_PRINTF("failed to configure SX1302 PA/LNA LUT\n"); + return LGW_HAL_ERROR; + } + + /* Configure Radio FE */ + err = sx1302_radio_fe_configure(); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to configure SX1302 radio frontend\n"); ++ ERROR_PRINTF("failed to configure SX1302 radio frontend\n"); + return LGW_HAL_ERROR; + } + + /* Configure the Channelizer */ + err = sx1302_channelizer_configure(CONTEXT_IF_CHAIN, false); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to configure SX1302 channelizer\n"); ++ ERROR_PRINTF("failed to configure SX1302 channelizer\n"); + return LGW_HAL_ERROR; + } + + /* configure LoRa 'multi-sf' modems */ + err = sx1302_lora_correlator_configure(CONTEXT_IF_CHAIN, &(CONTEXT_DEMOD)); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to configure SX1302 LoRa modem correlators\n"); ++ ERROR_PRINTF("failed to configure SX1302 LoRa modem correlators\n"); + return LGW_HAL_ERROR; + } + err = sx1302_lora_modem_configure(CONTEXT_RF_CHAIN[0].freq_hz); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to configure SX1302 LoRa modems\n"); ++ ERROR_PRINTF("failed to configure SX1302 LoRa modems\n"); + return LGW_HAL_ERROR; + } + +@@ -970,12 +974,12 @@ int lgw_start(void) { + if (CONTEXT_IF_CHAIN[8].enable == true) { + err = sx1302_lora_service_correlator_configure(&(CONTEXT_LORA_SERVICE)); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to configure SX1302 LoRa Service modem correlators\n"); ++ ERROR_PRINTF("failed to configure SX1302 LoRa Service modem correlators\n"); + return LGW_HAL_ERROR; + } + err = sx1302_lora_service_modem_configure(&(CONTEXT_LORA_SERVICE), CONTEXT_RF_CHAIN[0].freq_hz); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to configure SX1302 LoRa Service modem\n"); ++ ERROR_PRINTF("failed to configure SX1302 LoRa Service modem\n"); + return LGW_HAL_ERROR; + } + } +@@ -984,7 +988,7 @@ int lgw_start(void) { + if (CONTEXT_IF_CHAIN[9].enable == true) { + err = sx1302_fsk_configure(&(CONTEXT_FSK)); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to configure SX1302 FSK modem\n"); ++ ERROR_PRINTF("failed to configure SX1302 FSK modem\n"); + return LGW_HAL_ERROR; + } + } +@@ -992,14 +996,14 @@ int lgw_start(void) { + /* configure syncword */ + err = sx1302_lora_syncword(CONTEXT_LWAN_PUBLIC, CONTEXT_LORA_SERVICE.datarate); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to configure SX1302 LoRa syncword\n"); ++ ERROR_PRINTF("failed to configure SX1302 LoRa syncword\n"); + return LGW_HAL_ERROR; + } + + /* enable demodulators - to be done before starting AGC/ARB */ + err = sx1302_modem_enable(); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to enable SX1302 modems\n"); ++ ERROR_PRINTF("failed to enable SX1302 modems\n"); + return LGW_HAL_ERROR; + } + +@@ -1009,7 +1013,7 @@ int lgw_start(void) { + DEBUG_MSG("Loading AGC fw for sx1250\n"); + err = sx1302_agc_load_firmware(agc_firmware_sx1250); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to load AGC firmware for sx1250\n"); ++ ERROR_PRINTF("failed to load AGC firmware for sx1250\n"); + return LGW_HAL_ERROR; + } + fw_version_agc = FW_VERSION_AGC_SX1250; +@@ -1019,18 +1023,18 @@ int lgw_start(void) { + DEBUG_MSG("Loading AGC fw for sx125x\n"); + err = sx1302_agc_load_firmware(agc_firmware_sx125x); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to load AGC firmware for sx125x\n"); ++ ERROR_PRINTF("failed to load AGC firmware for sx125x\n"); + return LGW_HAL_ERROR; + } + fw_version_agc = FW_VERSION_AGC_SX125X; + break; + default: +- printf("ERROR: failed to load AGC firmware, radio type not supported (%d)\n", CONTEXT_RF_CHAIN[CONTEXT_BOARD.clksrc].type); ++ ERROR_PRINTF("failed to load AGC firmware, radio type not supported (%d)\n", CONTEXT_RF_CHAIN[CONTEXT_BOARD.clksrc].type); + return LGW_HAL_ERROR; + } + err = sx1302_agc_start(fw_version_agc, CONTEXT_RF_CHAIN[CONTEXT_BOARD.clksrc].type, SX1302_AGC_RADIO_GAIN_AUTO, SX1302_AGC_RADIO_GAIN_AUTO, CONTEXT_BOARD.full_duplex, CONTEXT_SX1261.lbt_conf.enable); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to start AGC firmware\n"); ++ ERROR_PRINTF("failed to start AGC firmware\n"); + return LGW_HAL_ERROR; + } + +@@ -1038,26 +1042,26 @@ int lgw_start(void) { + DEBUG_MSG("Loading ARB fw\n"); + err = sx1302_arb_load_firmware(arb_firmware); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to load ARB firmware\n"); ++ ERROR_PRINTF("failed to load ARB firmware\n"); + return LGW_HAL_ERROR; + } + err = sx1302_arb_start(FW_VERSION_ARB, &CONTEXT_FINE_TIMESTAMP); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to start ARB firmware\n"); ++ ERROR_PRINTF("failed to start ARB firmware\n"); + return LGW_HAL_ERROR; + } + + /* static TX configuration */ + err = sx1302_tx_configure(CONTEXT_RF_CHAIN[CONTEXT_BOARD.clksrc].type); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to configure SX1302 TX path\n"); ++ ERROR_PRINTF("failed to configure SX1302 TX path\n"); + return LGW_HAL_ERROR; + } + + /* enable GPS */ + err = sx1302_gps_enable(true); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to enable GPS on sx1302\n"); ++ ERROR_PRINTF("failed to enable GPS on sx1302\n"); + return LGW_HAL_ERROR; + } + +@@ -1075,7 +1079,7 @@ int lgw_start(void) { + /* Open the file for writting */ + log_file = fopen(CONTEXT_DEBUG.log_file_name, "w+"); /* create log file, overwrite if file already exist */ + if (log_file == NULL) { +- printf("ERROR: impossible to create log file %s\n", CONTEXT_DEBUG.log_file_name); ++ ERROR_PRINTF("impossible to create log file %s\n", CONTEXT_DEBUG.log_file_name); + return LGW_HAL_ERROR; + } else { + printf("INFO: %s file opened for debug log\n", CONTEXT_DEBUG.log_file_name); +@@ -1084,7 +1088,7 @@ int lgw_start(void) { + unlink("loragw_hal.log"); + i = symlink(CONTEXT_DEBUG.log_file_name, "loragw_hal.log"); + if (i < 0) { +- printf("ERROR: impossible to create symlink to log file %s\n", CONTEXT_DEBUG.log_file_name); ++ ERROR_PRINTF("impossible to create symlink to log file %s\n", CONTEXT_DEBUG.log_file_name); + } + } + #endif +@@ -1098,22 +1102,22 @@ int lgw_start(void) { + ts_addr = I2C_PORT_TEMP_SENSOR[i]; + err = i2c_linuxdev_open(I2C_DEVICE, ts_addr, &ts_fd); + if (err != LGW_I2C_SUCCESS) { +- printf("ERROR: failed to open I2C for temperature sensor on port 0x%02X\n", ts_addr); ++ ERROR_PRINTF("failed to open I2C for temperature sensor on port 0x%02X\n", ts_addr); + return LGW_HAL_ERROR; + } + + err = stts751_configure(ts_fd, ts_addr); + if (err != LGW_I2C_SUCCESS) { +- printf("INFO: no temperature sensor found on port 0x%02X\n", ts_addr); ++ INFO_PRINTF("no temperature sensor found on port 0x%02X\n", ts_addr); + i2c_linuxdev_close(ts_fd); + ts_fd = -1; + } else { +- printf("INFO: found temperature sensor on port 0x%02X\n", ts_addr); ++ INFO_PRINTF("found temperature sensor on port 0x%02X\n", ts_addr); + break; + } + } + if (i == sizeof I2C_PORT_TEMP_SENSOR) { +- printf("ERROR: no temperature sensor found.\n"); ++ ERROR_PRINTF("no temperature sensor found.\n"); + return LGW_HAL_ERROR; + } + +@@ -1121,13 +1125,13 @@ int lgw_start(void) { + if (CONTEXT_BOARD.full_duplex == true) { + err = i2c_linuxdev_open(I2C_DEVICE, I2C_PORT_DAC_AD5338R, &ad_fd); + if (err != LGW_I2C_SUCCESS) { +- printf("ERROR: failed to open I2C for ad5338r\n"); ++ ERROR_PRINTF("failed to open I2C for ad5338r\n"); + return LGW_HAL_ERROR; + } + + err = ad5338r_configure(ad_fd, I2C_PORT_DAC_AD5338R); + if (err != LGW_I2C_SUCCESS) { +- printf("ERROR: failed to configure ad5338r\n"); ++ ERROR_PRINTF("failed to configure ad5338r\n"); + i2c_linuxdev_close(ad_fd); + ad_fd = -1; + return LGW_HAL_ERROR; +@@ -1137,10 +1141,10 @@ int lgw_start(void) { + uint8_t volt_val[AD5338R_CMD_SIZE] = { 0x39, (uint8_t)VOLTAGE2HEX_H(0), (uint8_t)VOLTAGE2HEX_L(0) }; + err = ad5338r_write(ad_fd, I2C_PORT_DAC_AD5338R, volt_val); + if (err != LGW_I2C_SUCCESS) { +- printf("ERROR: AD5338R: failed to set DAC output to 0V\n"); ++ ERROR_PRINTF("AD5338R: failed to set DAC output to 0V\n"); + return LGW_HAL_ERROR; + } +- printf("INFO: AD5338R: Set DAC output to 0x%02X 0x%02X\n", (uint8_t)VOLTAGE2HEX_H(0), (uint8_t)VOLTAGE2HEX_L(0)); ++ INFO_PRINTF("AD5338R: Set DAC output to 0x%02X 0x%02X\n", (uint8_t)VOLTAGE2HEX_H(0), (uint8_t)VOLTAGE2HEX_L(0)); + } + } + +@@ -1148,25 +1152,25 @@ int lgw_start(void) { + if (CONTEXT_SX1261.enable == true) { + err = sx1261_connect(CONTEXT_COM_TYPE, (CONTEXT_COM_TYPE == LGW_COM_SPI) ? CONTEXT_SX1261.spi_path : NULL); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to connect to the sx1261 radio (LBT/Spectral Scan)\n"); ++ ERROR_PRINTF("failed to connect to the sx1261 radio (LBT/Spectral Scan)\n"); + return LGW_HAL_ERROR; + } + + err = sx1261_load_pram(); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to patch sx1261 radio for LBT/Spectral Scan\n"); ++ ERROR_PRINTF("failed to patch sx1261 radio for LBT/Spectral Scan\n"); + return LGW_HAL_ERROR; + } + + err = sx1261_calibrate(CONTEXT_RF_CHAIN[0].freq_hz); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to calibrate sx1261 radio\n"); ++ ERROR_PRINTF("failed to calibrate sx1261 radio\n"); + return LGW_HAL_ERROR; + } + + err = sx1261_setup(); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to setup sx1261 radio\n"); ++ ERROR_PRINTF("failed to setup sx1261 radio\n"); + return LGW_HAL_ERROR; + } + } +@@ -1174,7 +1178,7 @@ int lgw_start(void) { + /* Set CONFIG_DONE GPIO to 1 (turn on the corresponding LED) */ + err = sx1302_set_gpio(0x01); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to set CONFIG_DONE GPIO\n"); ++ ERROR_PRINTF("failed to set CONFIG_DONE GPIO\n"); + return LGW_HAL_ERROR; + } + +@@ -1203,7 +1207,7 @@ int lgw_stop(void) { + DEBUG_PRINTF("INFO: aborting TX on chain %u\n", i); + x = lgw_abort_tx(i); + if (x != LGW_HAL_SUCCESS) { +- printf("WARNING: failed to get abort TX on chain %u\n", i); ++ DEBUG_PRINTF("HAL WARNING: failed to get abort TX on chain %u\n", i); + err = LGW_HAL_ERROR; + } + } +@@ -1217,7 +1221,7 @@ int lgw_stop(void) { + DEBUG_MSG("INFO: Disconnecting\n"); + x = lgw_disconnect(); + if (x != LGW_HAL_SUCCESS) { +- printf("ERROR: failed to disconnect concentrator\n"); ++ ERROR_PRINTF("failed to disconnect concentrator\n"); + err = LGW_HAL_ERROR; + } + +@@ -1225,7 +1229,7 @@ int lgw_stop(void) { + DEBUG_MSG("INFO: Closing I2C for temperature sensor\n"); + x = i2c_linuxdev_close(ts_fd); + if (x != 0) { +- printf("ERROR: failed to close I2C temperature sensor device (err=%i)\n", x); ++ ERROR_PRINTF("failed to close I2C temperature sensor device (err=%i)\n", x); + err = LGW_HAL_ERROR; + } + +@@ -1233,7 +1237,7 @@ int lgw_stop(void) { + DEBUG_MSG("INFO: Closing I2C for AD5338R\n"); + x = i2c_linuxdev_close(ad_fd); + if (x != 0) { +- printf("ERROR: failed to close I2C AD5338R device (err=%i)\n", x); ++ ERROR_PRINTF("failed to close I2C AD5338R device (err=%i)\n", x); + err = LGW_HAL_ERROR; + } + } +@@ -1257,7 +1261,7 @@ int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { + /* performances variables */ + struct timeval tm; + +- DEBUG_PRINTF(" --- %s\n", "IN"); ++ // DEBUG_PRINTF(" --- %s\n", "IN"); + + /* Record function start time */ + _meas_time_start(&tm); +@@ -1265,7 +1269,7 @@ int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { + /* Get packets from SX1302, if any */ + res = sx1302_fetch(&nb_pkt_fetched); + if (res != LGW_REG_SUCCESS) { +- printf("ERROR: failed to fetch packets from SX1302\n"); ++ ERROR_PRINTF("failed to fetch packets from SX1302\n"); + return LGW_HAL_ERROR; + } + +@@ -1283,13 +1287,14 @@ int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { + } + if (nb_pkt_fetched > max_pkt) { + nb_pkt_left = nb_pkt_fetched - max_pkt; +- printf("WARNING: not enough space allocated, fetched %d packet(s), %d will be left in RX buffer\n", nb_pkt_fetched, nb_pkt_left); ++ (void) nb_pkt_left; ++ DEBUG_PRINTF("WARNING: not enough space allocated, fetched %d packet(s), %d will be left in RX buffer\n", nb_pkt_fetched, nb_pkt_left); + } + + /* Apply RSSI temperature compensation */ + res = lgw_get_temperature(¤t_temperature); + if (res != LGW_I2C_SUCCESS) { +- printf("ERROR: failed to get current temperature\n"); ++ ERROR_PRINTF("failed to get current temperature\n"); + return LGW_HAL_ERROR; + } + +@@ -1298,10 +1303,10 @@ int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { + /* Get packet and move to next one */ + res = sx1302_parse(&lgw_context, &pkt_data[nb_pkt_found]); + if (res == LGW_REG_WARNING) { +- printf("WARNING: parsing error on packet %d, discarding fetched packets\n", nb_pkt_found); ++ DEBUG_PRINTF("WARNING: parsing error on packet %d, discarding fetched packets\n", nb_pkt_found); + return LGW_HAL_SUCCESS; + } else if (res == LGW_REG_ERROR) { +- printf("ERROR: fatal parsing error on packet %d, aborting...\n", nb_pkt_found); ++ ERROR_PRINTF("fatal parsing error on packet %d, aborting...\n", nb_pkt_found); + return LGW_HAL_ERROR; + } + +@@ -1321,7 +1326,7 @@ int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { + if ((nb_pkt_found > 0) && (CONTEXT_FINE_TIMESTAMP.enable == true)) { + res = merge_packets(pkt_data, &nb_pkt_found); + if (res != 0) { +- printf("WARNING: failed to remove duplicated packets\n"); ++ DEBUG_PRINTF("WARNING: failed to remove duplicated packets\n"); + } + + DEBUG_PRINTF("INFO: nb pkt found:%u (after de-duplicating)\n", nb_pkt_found); +@@ -1349,7 +1354,7 @@ int lgw_send(struct lgw_pkt_tx_s * pkt_data) { + + /* check if the concentrator is running */ + if (CONTEXT_STARTED == false) { +- printf("ERROR: CONCENTRATOR IS NOT RUNNING, START IT BEFORE SENDING\n"); ++ ERROR_PRINTF("CONCENTRATOR IS NOT RUNNING, START IT BEFORE SENDING\n"); + return LGW_HAL_ERROR; + } + +@@ -1357,57 +1362,57 @@ int lgw_send(struct lgw_pkt_tx_s * pkt_data) { + + /* check input range (segfault prevention) */ + if (pkt_data->rf_chain >= LGW_RF_CHAIN_NB) { +- printf("ERROR: INVALID RF_CHAIN TO SEND PACKETS\n"); ++ ERROR_PRINTF("INVALID RF_CHAIN TO SEND PACKETS\n"); + return LGW_HAL_ERROR; + } + + /* check input variables */ + if (CONTEXT_RF_CHAIN[pkt_data->rf_chain].tx_enable == false) { +- printf("ERROR: SELECTED RF_CHAIN IS DISABLED FOR TX ON SELECTED BOARD\n"); ++ ERROR_PRINTF("SELECTED RF_CHAIN IS DISABLED FOR TX ON SELECTED BOARD\n"); + return LGW_HAL_ERROR; + } + if (CONTEXT_RF_CHAIN[pkt_data->rf_chain].enable == false) { +- printf("ERROR: SELECTED RF_CHAIN IS DISABLED\n"); ++ ERROR_PRINTF("SELECTED RF_CHAIN IS DISABLED\n"); + return LGW_HAL_ERROR; + } + if (!IS_TX_MODE(pkt_data->tx_mode)) { +- printf("ERROR: TX_MODE NOT SUPPORTED\n"); ++ ERROR_PRINTF("TX_MODE NOT SUPPORTED\n"); + return LGW_HAL_ERROR; + } + if (pkt_data->modulation == MOD_LORA) { + if (!IS_LORA_BW(pkt_data->bandwidth)) { +- printf("ERROR: BANDWIDTH NOT SUPPORTED BY LORA TX\n"); ++ ERROR_PRINTF("BANDWIDTH NOT SUPPORTED BY LORA TX\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_DR(pkt_data->datarate)) { +- printf("ERROR: DATARATE NOT SUPPORTED BY LORA TX\n"); ++ ERROR_PRINTF("DATARATE NOT SUPPORTED BY LORA TX\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_CR(pkt_data->coderate)) { +- printf("ERROR: CODERATE NOT SUPPORTED BY LORA TX\n"); ++ ERROR_PRINTF("CODERATE NOT SUPPORTED BY LORA TX\n"); + return LGW_HAL_ERROR; + } + if (pkt_data->size > 255) { +- printf("ERROR: PAYLOAD LENGTH TOO BIG FOR LORA TX\n"); ++ ERROR_PRINTF("PAYLOAD LENGTH TOO BIG FOR LORA TX\n"); + return LGW_HAL_ERROR; + } + } else if (pkt_data->modulation == MOD_FSK) { + if((pkt_data->f_dev < 1) || (pkt_data->f_dev > 200)) { +- printf("ERROR: TX FREQUENCY DEVIATION OUT OF ACCEPTABLE RANGE\n"); ++ ERROR_PRINTF("TX FREQUENCY DEVIATION OUT OF ACCEPTABLE RANGE\n"); + return LGW_HAL_ERROR; + } + if(!IS_FSK_DR(pkt_data->datarate)) { +- printf("ERROR: DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); ++ ERROR_PRINTF("DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); + return LGW_HAL_ERROR; + } + if (pkt_data->size > 255) { +- printf("ERROR: PAYLOAD LENGTH TOO BIG FOR FSK TX\n"); ++ ERROR_PRINTF("PAYLOAD LENGTH TOO BIG FOR FSK TX\n"); + return LGW_HAL_ERROR; + } + } else if (pkt_data->modulation == MOD_CW) { + /* do nothing */ + } else { +- printf("ERROR: INVALID TX MODULATION\n"); ++ ERROR_PRINTF("INVALID TX MODULATION\n"); + return LGW_HAL_ERROR; + } + +@@ -1416,17 +1421,17 @@ int lgw_send(struct lgw_pkt_tx_s * pkt_data) { + uint8_t volt_val[AD5338R_CMD_SIZE] = {0x39, VOLTAGE2HEX_H(2.51), VOLTAGE2HEX_L(2.51)}; /* set to 2.51V */ + err = ad5338r_write(ad_fd, I2C_PORT_DAC_AD5338R, volt_val); + if (err != LGW_I2C_SUCCESS) { +- printf("ERROR: failed to set voltage by ad5338r\n"); ++ ERROR_PRINTF("failed to set voltage by ad5338r\n"); + return LGW_HAL_ERROR; + } +- printf("INFO: AD5338R: Set DAC output to 0x%02X 0x%02X\n", (uint8_t)VOLTAGE2HEX_H(2.51), (uint8_t)VOLTAGE2HEX_L(2.51)); ++ DEBUG_PRINTF("INFO: AD5338R: Set DAC output to 0x%02X 0x%02X\n", (uint8_t)VOLTAGE2HEX_H(2.51), (uint8_t)VOLTAGE2HEX_L(2.51)); + } + + /* Start Listen-Before-Talk */ + if (CONTEXT_SX1261.lbt_conf.enable == true) { + err = lgw_lbt_start(&CONTEXT_SX1261, pkt_data); + if (err != 0) { +- printf("ERROR: failed to start LBT\n"); ++ ERROR_PRINTF("failed to start LBT\n"); + return LGW_HAL_ERROR; + } + } +@@ -1434,12 +1439,12 @@ int lgw_send(struct lgw_pkt_tx_s * pkt_data) { + /* Send the TX request to the concentrator */ + err = sx1302_send(CONTEXT_RF_CHAIN[pkt_data->rf_chain].type, &CONTEXT_TX_GAIN_LUT[pkt_data->rf_chain], CONTEXT_LWAN_PUBLIC, &CONTEXT_FSK, pkt_data); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: %s: Failed to send packet\n", __FUNCTION__); ++ ERROR_PRINTF("Failed to send packet\n"); + + if (CONTEXT_SX1261.lbt_conf.enable == true) { + err = lgw_lbt_stop(); + if (err != 0) { +- printf("ERROR: %s: Failed to stop LBT\n", __FUNCTION__); ++ ERROR_PRINTF("Failed to stop LBT\n"); + } + } + +@@ -1452,26 +1457,26 @@ int lgw_send(struct lgw_pkt_tx_s * pkt_data) { + if (CONTEXT_SX1261.lbt_conf.enable == true) { + err = lgw_lbt_tx_status(pkt_data->rf_chain, &lbt_tx_allowed); + if (err != 0) { +- printf("ERROR: %s: Failed to get LBT TX status, TX aborted\n", __FUNCTION__); ++ ERROR_PRINTF("Failed to get LBT TX status, TX aborted\n"); + err = sx1302_tx_abort(pkt_data->rf_chain); + if (err != 0) { +- printf("ERROR: %s: Failed to abort TX\n", __FUNCTION__); ++ ERROR_PRINTF("Failed to abort TX\n"); + } + err = lgw_lbt_stop(); + if (err != 0) { +- printf("ERROR: %s: Failed to stop LBT\n", __FUNCTION__); ++ ERROR_PRINTF("Failed to stop LBT\n"); + } + return LGW_HAL_ERROR; + } + if (lbt_tx_allowed == true) { +- printf("LBT: packet is allowed to be transmitted\n"); ++ DEBUG_PRINTF("LBT: packet is allowed to be transmitted\n"); + } else { +- printf("LBT: (ERROR) packet is NOT allowed to be transmitted\n"); ++ DEBUG_PRINTF("LBT: (ERROR) packet is NOT allowed to be transmitted\n"); + } + + err = lgw_lbt_stop(); + if (err != 0) { +- printf("ERROR: %s: Failed to stop LBT\n", __FUNCTION__); ++ ERROR_PRINTF("Failed to stop LBT\n"); + return LGW_HAL_ERROR; + } + } +@@ -1493,7 +1498,7 @@ int lgw_status(uint8_t rf_chain, uint8_t select, uint8_t *code) { + /* check input variables */ + CHECK_NULL(code); + if (rf_chain >= LGW_RF_CHAIN_NB) { +- DEBUG_MSG("ERROR: NOT A VALID RF_CHAIN NUMBER\n"); ++ ERROR_PRINTF("NOT A VALID RF_CHAIN NUMBER\n"); + return LGW_HAL_ERROR; + } + +@@ -1511,7 +1516,7 @@ int lgw_status(uint8_t rf_chain, uint8_t select, uint8_t *code) { + *code = sx1302_rx_status(rf_chain); + } + } else { +- DEBUG_MSG("ERROR: SELECTION INVALID, NO STATUS TO RETURN\n"); ++ ERROR_PRINTF("SELECTION INVALID, NO STATUS TO RETURN\n"); + return LGW_HAL_ERROR; + } + +@@ -1530,7 +1535,7 @@ int lgw_abort_tx(uint8_t rf_chain) { + + /* check input variables */ + if (rf_chain >= LGW_RF_CHAIN_NB) { +- DEBUG_MSG("ERROR: NOT A VALID RF_CHAIN NUMBER\n"); ++ ERROR_PRINTF("NOT A VALID RF_CHAIN NUMBER\n"); + return LGW_HAL_ERROR; + } + +@@ -1591,7 +1596,7 @@ int lgw_get_eui(uint64_t* eui) { + int lgw_get_temperature(float* temperature) { + int err = LGW_HAL_ERROR; + +- DEBUG_PRINTF(" --- %s\n", "IN"); ++ // DEBUG_PRINTF(" --- %s\n", "IN"); + + CHECK_NULL(temperature); + +@@ -1603,11 +1608,11 @@ int lgw_get_temperature(float* temperature) { + err = lgw_com_get_temperature(temperature); + break; + default: +- printf("ERROR(%s:%d): wrong communication type (SHOULD NOT HAPPEN)\n", __FUNCTION__, __LINE__); ++ ERROR_PRINTF("wrong communication type (SHOULD NOT HAPPEN)\n"); + break; + } + +- DEBUG_PRINTF(" --- %s\n", "OUT"); ++ // DEBUG_PRINTF(" --- %s\n", "OUT"); + + return err; + } +@@ -1627,7 +1632,7 @@ uint32_t lgw_time_on_air(const struct lgw_pkt_tx_s *packet) { + DEBUG_PRINTF(" --- %s\n", "IN"); + + if (packet == NULL) { +- printf("ERROR: Failed to compute time on air, wrong parameter\n"); ++ ERROR_PRINTF("Failed to compute time on air, wrong parameter\n"); + return 0; + } + +@@ -1649,7 +1654,7 @@ uint32_t lgw_time_on_air(const struct lgw_pkt_tx_s *packet) { + toa_ms = (uint32_t)t_fsk + 1; /* add margin for rounding */ + } else { + toa_ms = 0; +- printf("ERROR: Cannot compute time on air for this packet, unsupported modulation (0x%02X)\n", packet->modulation); ++ ERROR_PRINTF("Cannot compute time on air for this packet, unsupported modulation (0x%02X)\n", packet->modulation); + } + + DEBUG_PRINTF(" --- %s\n", "OUT"); +@@ -1663,19 +1668,19 @@ int lgw_spectral_scan_start(uint32_t freq_hz, uint16_t nb_scan) { + int err; + + if (CONTEXT_SX1261.enable != true) { +- printf("ERROR: sx1261 is not enabled, no spectral scan\n"); ++ ERROR_PRINTF("sx1261 is not enabled, no spectral scan\n"); + return LGW_HAL_ERROR; + } + + err = sx1261_set_rx_params(freq_hz, BW_125KHZ); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: Failed to set RX params for Spectral Scan\n"); ++ ERROR_PRINTF("Failed to set RX params for Spectral Scan\n"); + return LGW_HAL_ERROR; + } + + err = sx1261_spectral_scan_start(nb_scan); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: start spectral scan failed\n"); ++ ERROR_PRINTF("start spectral scan failed\n"); + return LGW_HAL_ERROR; + } + +diff --git a/libloragw/src/loragw_i2c.c b/libloragw/src/loragw_i2c.c +index 87e8b3a..193ed58 100644 +--- a/libloragw/src/loragw_i2c.c ++++ b/libloragw/src/loragw_i2c.c +@@ -21,6 +21,7 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + #include /* lseek, close */ + #include /* open */ + #include /* errno */ ++#include /* strerror */ + + #include + #include +@@ -43,6 +44,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + #define CHECK_NULL(a) if(a==NULL){return LGW_I2C_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + +diff --git a/libloragw/src/loragw_lbt.c b/libloragw/src/loragw_lbt.c +index e298c42..b585fe4 100644 +--- a/libloragw/src/loragw_lbt.c ++++ b/libloragw/src/loragw_lbt.c +@@ -43,6 +43,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + #define DEBUG_PRINTF(fmt, args...) + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE FUNCTIONS DEFINITION ----------------------------------------- */ + +diff --git a/libloragw/src/loragw_mcu.c b/libloragw/src/loragw_mcu.c +index 4644df8..1d05002 100644 +--- a/libloragw/src/loragw_mcu.c ++++ b/libloragw/src/loragw_mcu.c +@@ -44,6 +44,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + #define CHECK_NULL(a) if(a==NULL){return -1;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + +@@ -235,8 +237,8 @@ int write_req(int fd, order_id_t cmd, const uint8_t * payload, uint16_t payload_ + + #if DEBUG_MCU == 1 + gettimeofday(&write_tv, NULL); +-#endif + DEBUG_PRINTF("\nINFO: %ld.%ld: write_req 0x%02X (%s) done, id:0x%02X, size:%u\n", write_tv.tv_sec, write_tv.tv_usec, cmd, cmd_get_str(cmd), buf_w[0], payload_size); ++#endif + + #if DEBUG_VERBOSE + int i; +@@ -285,8 +287,8 @@ int read_ack(int fd, uint8_t * hdr, uint8_t * buf, size_t buf_size) { + } else { + #if DEBUG_MCU == 1 + gettimeofday(&read_tv, NULL); +-#endif + DEBUG_PRINTF("INFO: %ld.%ld: read %d bytes for header from gateway\n", read_tv.tv_sec, read_tv.tv_usec, n); ++#endif + } + + /* Compute time spent in this function */ +@@ -331,8 +333,8 @@ int read_ack(int fd, uint8_t * hdr, uint8_t * buf, size_t buf_size) { + } else { + #if DEBUG_MCU == 1 + gettimeofday(&read_tv, NULL); +-#endif + DEBUG_PRINTF("INFO: %ld.%ld: read %d bytes from gateway\n", read_tv.tv_sec, read_tv.tv_usec, n); ++#endif + nb_read += n; + } + } while (nb_read < (int)size); /* we want to read only the expected payload, not more */ +diff --git a/libloragw/src/loragw_reg.c b/libloragw/src/loragw_reg.c +index 6a7d0df..8019654 100644 +--- a/libloragw/src/loragw_reg.c ++++ b/libloragw/src/loragw_reg.c +@@ -39,6 +39,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + #define CHECK_NULL(a) if(a==NULL){return LGW_REG_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + +@@ -1170,24 +1172,24 @@ int lgw_connect(const lgw_com_type_t com_type, const char * com_path) { + + /* check COM link status */ + if (com_path == NULL) { +- DEBUG_MSG("ERROR: COM PATH IS NOT SET\n"); ++ ERROR_PRINTF("COM PATH IS NOT SET\n"); + return LGW_REG_ERROR; + } + + /* open the COM link */ + com_stat = lgw_com_open(com_type, com_path); + if (com_stat != LGW_COM_SUCCESS) { +- DEBUG_MSG("ERROR CONNECTING CONCENTRATOR\n"); ++ ERROR_PRINTF("CONNECTING CONCENTRATOR FAILED\n"); + return LGW_REG_ERROR; + } + + /* check SX1302 version */ + com_stat = lgw_com_r(LGW_SPI_MUX_TARGET_SX1302, loregs[SX1302_REG_COMMON_VERSION_VERSION].addr, &u); + if (com_stat != LGW_COM_SUCCESS) { +- DEBUG_MSG("ERROR READING CHIP VERSION REGISTER\n"); ++ ERROR_PRINTF("READING CHIP VERSION REGISTER\n"); + return LGW_REG_ERROR; + } +- printf("Note: chip version is 0x%02X (v%u.%u)\n", u, (u >> 4) & 0x0F, u & 0x0F) ; ++ INFO_PRINTF("chip version is 0x%02X (v%u.%u)\n", u, (u >> 4) & 0x0F, u & 0x0F) ; + + DEBUG_MSG("Note: success connecting the concentrator\n"); + return LGW_REG_SUCCESS; +@@ -1204,7 +1206,7 @@ int lgw_disconnect(void) { + DEBUG_MSG("Note: success disconnecting the concentrator\n"); + return LGW_REG_SUCCESS; + } else { +- DEBUG_MSG("ERROR: Failed to disconnect the concentrator\n"); ++ ERROR_PRINTF("Failed to disconnect the concentrator\n"); + return LGW_REG_ERROR; + } + } +@@ -1218,7 +1220,7 @@ int lgw_reg_w(uint16_t register_id, int32_t reg_value) { + + /* check input parameters */ + if (register_id >= LGW_TOTALREGS) { +- DEBUG_MSG("ERROR: REGISTER NUMBER OUT OF DEFINED RANGE\n"); ++ ERROR_PRINTF("REGISTER NUMBER OUT OF DEFINED RANGE\n"); + return LGW_REG_ERROR; + } + +@@ -1227,14 +1229,14 @@ int lgw_reg_w(uint16_t register_id, int32_t reg_value) { + + /* reject write to read-only registers */ + if (r.rdon == 1){ +- DEBUG_MSG("ERROR: TRYING TO WRITE A READ-ONLY REGISTER\n"); ++ ERROR_PRINTF("TRYING TO WRITE A READ-ONLY REGISTER\n"); + return LGW_REG_ERROR; + } + + com_stat = reg_w(LGW_SPI_MUX_TARGET_SX1302, r, reg_value); + + if (com_stat != LGW_COM_SUCCESS) { +- DEBUG_MSG("ERROR: COM ERROR DURING REGISTER WRITE\n"); ++ ERROR_PRINTF("COM ERROR DURING REGISTER WRITE\n"); + return LGW_REG_ERROR; + } else { + return LGW_REG_SUCCESS; +@@ -1251,7 +1253,7 @@ int lgw_reg_r(uint16_t register_id, int32_t *reg_value) { + /* check input parameters */ + CHECK_NULL(reg_value); + if (register_id >= LGW_TOTALREGS) { +- DEBUG_MSG("ERROR: REGISTER NUMBER OUT OF DEFINED RANGE\n"); ++ ERROR_PRINTF("REGISTER NUMBER OUT OF DEFINED RANGE\n"); + return LGW_REG_ERROR; + } + +@@ -1261,7 +1263,7 @@ int lgw_reg_r(uint16_t register_id, int32_t *reg_value) { + com_stat = reg_r(LGW_SPI_MUX_TARGET_SX1302, r, reg_value); + + if (com_stat != LGW_COM_SUCCESS) { +- DEBUG_MSG("ERROR: COM ERROR DURING REGISTER WRITE\n"); ++ ERROR_PRINTF("COM ERROR DURING REGISTER WRITE\n"); + return LGW_REG_ERROR; + } else { + return LGW_REG_SUCCESS; +@@ -1278,11 +1280,11 @@ int lgw_reg_wb(uint16_t register_id, uint8_t *data, uint16_t size) { + /* check input parameters */ + CHECK_NULL(data); + if (size == 0) { +- DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); ++ ERROR_PRINTF("BURST OF NULL LENGTH\n"); + return LGW_REG_ERROR; + } + if (register_id >= LGW_TOTALREGS) { +- DEBUG_MSG("ERROR: REGISTER NUMBER OUT OF DEFINED RANGE\n"); ++ ERROR_PRINTF("REGISTER NUMBER OUT OF DEFINED RANGE\n"); + return LGW_REG_ERROR; + } + +@@ -1291,7 +1293,7 @@ int lgw_reg_wb(uint16_t register_id, uint8_t *data, uint16_t size) { + + /* reject write to read-only registers */ + if (r.rdon == 1){ +- DEBUG_MSG("ERROR: TRYING TO BURST WRITE A READ-ONLY REGISTER\n"); ++ ERROR_PRINTF("TRYING TO BURST WRITE A READ-ONLY REGISTER\n"); + return LGW_REG_ERROR; + } + +@@ -1299,7 +1301,7 @@ int lgw_reg_wb(uint16_t register_id, uint8_t *data, uint16_t size) { + com_stat = lgw_com_wb(LGW_SPI_MUX_TARGET_SX1302, r.addr, data, size); + + if (com_stat != LGW_COM_SUCCESS) { +- DEBUG_MSG("ERROR: COM ERROR DURING REGISTER BURST WRITE\n"); ++ ERROR_PRINTF("COM ERROR DURING REGISTER BURST WRITE\n"); + return LGW_REG_ERROR; + } else { + return LGW_REG_SUCCESS; +@@ -1316,11 +1318,11 @@ int lgw_reg_rb(uint16_t register_id, uint8_t *data, uint16_t size) { + /* check input parameters */ + CHECK_NULL(data); + if (size == 0) { +- DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); ++ ERROR_PRINTF("BURST OF NULL LENGTH\n"); + return LGW_REG_ERROR; + } + if (register_id >= LGW_TOTALREGS) { +- DEBUG_MSG("ERROR: REGISTER NUMBER OUT OF DEFINED RANGE\n"); ++ ERROR_PRINTF("REGISTER NUMBER OUT OF DEFINED RANGE\n"); + return LGW_REG_ERROR; + } + +@@ -1331,7 +1333,7 @@ int lgw_reg_rb(uint16_t register_id, uint8_t *data, uint16_t size) { + com_stat = lgw_com_rb(LGW_SPI_MUX_TARGET_SX1302, r.addr, data, size); + + if (com_stat != LGW_COM_SUCCESS) { +- DEBUG_MSG("ERROR: COM ERROR DURING REGISTER BURST READ\n"); ++ ERROR_PRINTF("COM ERROR DURING REGISTER BURST READ\n"); + return LGW_REG_ERROR; + } else { + return LGW_REG_SUCCESS; +@@ -1351,7 +1353,7 @@ int lgw_mem_wb(uint16_t mem_addr, const uint8_t *data, uint16_t size) { + /* check input parameters */ + CHECK_NULL(data); + if (size == 0) { +- DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); ++ ERROR_PRINTF("BURST OF NULL LENGTH\n"); + return LGW_REG_ERROR; + } + +@@ -1370,7 +1372,7 @@ int lgw_mem_wb(uint16_t mem_addr, const uint8_t *data, uint16_t size) { + } + + if (com_stat != LGW_COM_SUCCESS) { +- DEBUG_MSG("ERROR: COM ERROR DURING REGISTER BURST WRITE\n"); ++ ERROR_PRINTF("COM ERROR DURING REGISTER BURST WRITE\n"); + return LGW_REG_ERROR; + } else { + return LGW_REG_SUCCESS; +@@ -1390,7 +1392,7 @@ int lgw_mem_rb(uint16_t mem_addr, uint8_t *data, uint16_t size, bool fifo_mode) + /* check input parameters */ + CHECK_NULL(data); + if (size == 0) { +- DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); ++ ERROR_PRINTF("BURST OF NULL LENGTH\n"); + return LGW_REG_ERROR; + } + +@@ -1413,7 +1415,7 @@ int lgw_mem_rb(uint16_t mem_addr, uint8_t *data, uint16_t size, bool fifo_mode) + } + + if (com_stat != LGW_COM_SUCCESS) { +- DEBUG_MSG("ERROR: COM ERROR DURING REGISTER BURST READ\n"); ++ ERROR_PRINTF("COM ERROR DURING REGISTER BURST READ\n"); + return LGW_REG_ERROR; + } else { + return LGW_REG_SUCCESS; +diff --git a/libloragw/src/loragw_spi.c b/libloragw/src/loragw_spi.c +index 94231b7..a90f8a2 100644 +--- a/libloragw/src/loragw_spi.c ++++ b/libloragw/src/loragw_spi.c +@@ -46,6 +46,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + #define CHECK_NULL(a) if(a==NULL){return LGW_SPI_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + +@@ -83,6 +85,7 @@ int lgw_spi_open(const char * com_path, void **com_target_ptr) { + } + + /* setting SPI mode to 'mode 0' */ ++ INFO_PRINTF("Setting SPI speed to %u\n", SPI_SPEED); + i = SPI_MODE_0; + a = ioctl(dev, SPI_IOC_WR_MODE, &i); + b = ioctl(dev, SPI_IOC_RD_MODE, &i); +@@ -359,7 +362,7 @@ int lgw_spi_rb(void *com_target, uint8_t spi_mux_target, uint16_t address, uint8 + k[1].rx_buf = (unsigned long)(data + offset); + k[1].len = chunk_size; + byte_transfered += (ioctl(spi_device, SPI_IOC_MESSAGE(2), &k) - k[0].len ); +- DEBUG_PRINTF("BURST READ: to trans %d # chunk %d # transferred %d \n", size_to_do, chunk_size, byte_transfered); ++ // XDEBUG_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 */ + } + +@@ -368,7 +371,7 @@ int lgw_spi_rb(void *com_target, uint8_t spi_mux_target, uint16_t address, uint8 + DEBUG_MSG("ERROR: SPI BURST READ FAILURE\n"); + return LGW_SPI_ERROR; + } else { +- DEBUG_MSG("Note: SPI burst read success\n"); ++ // DEBUG_MSG("Note: SPI burst read success\n"); + return LGW_SPI_SUCCESS; + } + } +diff --git a/libloragw/src/loragw_sx1302.c b/libloragw/src/loragw_sx1302.c +index aa330cd..ab58109 100644 +--- a/libloragw/src/loragw_sx1302.c ++++ b/libloragw/src/loragw_sx1302.c +@@ -49,6 +49,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + #endif + #define CHECK_ERR(a) if(a==-1){return LGW_REG_ERROR;} + ++#include "loragw_stationlog.h" ++ + #define IF_HZ_TO_REG(f) ((f * 32) / 15625) + + #define SX1302_FREQ_TO_REG(f) (uint32_t)((uint64_t)f * (1 << 18) / 32000000U) +@@ -171,7 +173,7 @@ int calculate_freq_to_time_drift(uint32_t freq_hz, uint8_t bw, uint16_t * mant, + + bw_hz = lgw_bw_getval(bw); + if (bw_hz < 0) { +- printf("ERROR: Unsupported bandwidth for frequency to time drift calculation\n"); ++ ERROR_PRINTF("Unsupported bandwidth for frequency to time drift calculation\n"); + return LGW_REG_ERROR; + } + +@@ -257,24 +259,24 @@ int sx1302_init(const struct lgw_conf_ftime_s * ftime_context) { + if (ftime_context->enable == true) { + x = sx1302_get_model_id(&model_id); + if (x != LGW_REG_SUCCESS) { +- printf("ERROR: failed to get Chip Model ID\n"); ++ ERROR_PRINTF("failed to get Chip Model ID\n"); + return LGW_REG_ERROR; + } + + if (model_id != CHIP_MODEL_ID_SX1303) { +- printf("ERROR: Fine Timestamping is not supported on this Chip Model ID 0x%02X\n", model_id); ++ ERROR_PRINTF("Fine Timestamping is not supported on this Chip Model ID 0x%02X\n", model_id); + return LGW_REG_ERROR; + } + } + x = timestamp_counter_mode(ftime_context->enable); + if (x != LGW_REG_SUCCESS) { +- printf("ERROR: failed to configure timestamp counter mode\n"); ++ ERROR_PRINTF("failed to configure timestamp counter mode\n"); + return LGW_REG_ERROR; + } + + x = sx1302_config_gpio(); + if (x != LGW_REG_SUCCESS) { +- printf("ERROR: failed to configure sx1302 GPIOs\n"); ++ ERROR_PRINTF("failed to configure sx1302 GPIOs\n"); + return LGW_REG_ERROR; + } + +@@ -396,7 +398,7 @@ int sx1302_radio_clock_select(uint8_t rf_chain) { + + /* Check if something went wrong */ + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to select radio clock for radio_%u\n", rf_chain); ++ ERROR_PRINTF("failed to select radio clock for radio_%u\n", rf_chain); + return LGW_REG_ERROR; + } + +@@ -451,7 +453,7 @@ int sx1302_radio_reset(uint8_t rf_chain, lgw_radio_type_t type) { + + /* Check if something went wrong */ + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to reset the radios\n"); ++ ERROR_PRINTF("failed to reset the radios\n"); + return LGW_REG_ERROR; + } + +@@ -466,11 +468,11 @@ int sx1302_radio_set_mode(uint8_t rf_chain, lgw_radio_type_t type) { + + /* Check input parameters */ + if (rf_chain >= LGW_RF_CHAIN_NB) { +- DEBUG_MSG("ERROR: invalid RF chain\n"); ++ ERROR_PRINTF("ERROR: invalid RF chain\n"); + return LGW_REG_ERROR; + } + if ((type != LGW_RADIO_TYPE_SX1255) && (type != LGW_RADIO_TYPE_SX1257) && (type != LGW_RADIO_TYPE_SX1250)) { +- DEBUG_MSG("ERROR: invalid radio type\n"); ++ ERROR_PRINTF("ERROR: invalid radio type\n"); + return LGW_REG_ERROR; + } + +@@ -488,7 +490,7 @@ int sx1302_radio_set_mode(uint8_t rf_chain, lgw_radio_type_t type) { + break; + } + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to set mode for radio %u\n", rf_chain); ++ ERROR_PRINTF("failed to set mode for radio %u\n", rf_chain); + return LGW_REG_ERROR; + } + +@@ -512,13 +514,13 @@ int sx1302_radio_calibrate(struct lgw_conf_rxrf_s * context_rf_chain, uint8_t cl + if (context_rf_chain[i].enable == true) { + err = sx1302_radio_reset(i, context_rf_chain[i].type); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to reset radio %d\n", i); ++ ERROR_PRINTF("failed to reset radio %d\n", i); + return LGW_REG_ERROR; + } + + err = sx1302_radio_set_mode(i, context_rf_chain[i].type); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to set radio %d mode\n", i); ++ ERROR_PRINTF("failed to set radio %d mode\n", i); + return LGW_REG_ERROR; + } + } +@@ -526,7 +528,7 @@ int sx1302_radio_calibrate(struct lgw_conf_rxrf_s * context_rf_chain, uint8_t cl + /* -- Select the radio which provides the clock to the sx1302 */ + err = sx1302_radio_clock_select(clksrc); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: failed to get select clock from radio %u\n", clksrc); ++ ERROR_PRINTF("failed to get select clock from radio %u\n", clksrc); + return LGW_REG_ERROR; + } + +@@ -540,12 +542,12 @@ int sx1302_radio_calibrate(struct lgw_conf_rxrf_s * context_rf_chain, uint8_t cl + DEBUG_MSG("Loading CAL fw for sx125x\n"); + err = sx1302_agc_load_firmware(cal_firmware_sx125x); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: Failed to load calibration fw\n"); ++ ERROR_PRINTF("Failed to load calibration fw\n"); + return LGW_REG_ERROR; + } + err = sx1302_cal_start(FW_VERSION_CAL, context_rf_chain, txgain_lut); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: radio calibration failed\n"); ++ ERROR_PRINTF("radio calibration failed\n"); + sx1302_radio_reset(0, context_rf_chain[0].type); + sx1302_radio_reset(1, context_rf_chain[1].type); + return LGW_REG_ERROR; +@@ -556,7 +558,7 @@ int sx1302_radio_calibrate(struct lgw_conf_rxrf_s * context_rf_chain, uint8_t cl + if (context_rf_chain[i].enable == true) { + err = sx1250_calibrate(i, context_rf_chain[i].freq_hz); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: radio calibration failed\n"); ++ ERROR_PRINTF("radio calibration failed\n"); + return LGW_REG_ERROR; + } + } +@@ -871,7 +873,7 @@ int sx1302_lora_service_correlator_configure(struct lgw_conf_rxif_s * cfg) { + err |= lgw_reg_w(SX1302_REG_RX_TOP_LORA_SERVICE_FSK_DETECT_ACC1_ACC_PNR, 52); + break; + default: +- printf("ERROR: Failed to configure LoRa service modem correlators\n"); ++ ERROR_PRINTF("Failed to configure LoRa service modem correlators\n"); + return LGW_REG_ERROR; + } + +@@ -972,7 +974,7 @@ int sx1302_lora_modem_configure(uint32_t radio_freq_hz) { + + /* Freq2TimeDrift computation */ + if (calculate_freq_to_time_drift(radio_freq_hz, BW_125KHZ, &mantissa, &exponent) != 0) { +- printf("ERROR: failed to calculate frequency to time drift for LoRa modem\n"); ++ ERROR_PRINTF("failed to calculate frequency to time drift for LoRa modem\n"); + return LGW_REG_ERROR; + } + DEBUG_PRINTF("Freq2TimeDrift MultiSF: Mantissa = %d (0x%02X, 0x%02X), Exponent = %d (0x%02X)\n", mantissa, (mantissa >> 8) & 0x00FF, (mantissa) & 0x00FF, exponent, exponent); +@@ -1032,12 +1034,12 @@ int sx1302_lora_service_modem_configure(struct lgw_conf_rxif_s * cfg, uint32_t r + err |= lgw_reg_w(SX1302_REG_RX_TOP_LORA_SERVICE_FSK_FINE_TIMING2_GAIN_I_EN, 0x03); + break; + default: +- printf("ERROR: unsupported bandwidth %u for LoRa Service modem\n", cfg->bandwidth); ++ ERROR_PRINTF("unsupported bandwidth %u for LoRa Service modem\n", cfg->bandwidth); + break; + } + break; + default: +- printf("ERROR: unsupported datarate %u for LoRa Service modem\n", cfg->datarate); ++ ERROR_PRINTF("unsupported datarate %u for LoRa Service modem\n", cfg->datarate); + break; + } + +@@ -1056,13 +1058,13 @@ int sx1302_lora_service_modem_configure(struct lgw_conf_rxif_s * cfg, uint32_t r + } else { + preamble_nb_symb = 8; + } +- printf("INFO: LoRa Service modem: configuring preamble size to %u symbols\n", preamble_nb_symb); ++ DEBUG_PRINTF("INFO: LoRa Service modem: configuring preamble size to %u symbols\n", preamble_nb_symb); + err |= lgw_reg_w(SX1302_REG_RX_TOP_LORA_SERVICE_FSK_TXRX_CFG7_PREAMBLE_SYMB_NB, (preamble_nb_symb >> 8) & 0xFF); /* MSB */ + err |= lgw_reg_w(SX1302_REG_RX_TOP_LORA_SERVICE_FSK_TXRX_CFG6_PREAMBLE_SYMB_NB, (preamble_nb_symb >> 0) & 0xFF); /* LSB */ + + /* Freq2TimeDrift computation */ + if (calculate_freq_to_time_drift(radio_freq_hz, cfg->bandwidth, &mantissa, &exponent) != 0) { +- printf("ERROR: failed to calculate frequency to time drift for LoRa service modem\n"); ++ ERROR_PRINTF("failed to calculate frequency to time drift for LoRa service modem\n"); + return LGW_REG_ERROR; + } + err |= lgw_reg_w(SX1302_REG_RX_TOP_LORA_SERVICE_FSK_FREQ_TO_TIME0_FREQ_TO_TIME_DRIFT_MANT, (mantissa >> 8) & 0x00FF); +@@ -1182,7 +1184,7 @@ int sx1302_agc_load_firmware(const uint8_t *firmware) { + /* Read back and check */ + err |= lgw_mem_rb(AGC_MEM_ADDR, fw_check, MCU_FW_SIZE, false); + if (memcmp(firmware, fw_check, sizeof fw_check) != 0) { +- printf("ERROR: AGC fw read/write check failed\n"); ++ ERROR_PRINTF("AGC fw read/write check failed\n"); + return LGW_REG_ERROR; + } + +@@ -1192,7 +1194,7 @@ int sx1302_agc_load_firmware(const uint8_t *firmware) { + + err |= lgw_reg_r(SX1302_REG_AGC_MCU_CTRL_PARITY_ERROR, &val); + if (val != 0) { +- printf("ERROR: Failed to load AGC fw: parity error check failed\n"); ++ ERROR_PRINTF("Failed to load AGC fw: parity error check failed\n"); + return LGW_REG_ERROR; + } + DEBUG_MSG("AGC fw loaded\n"); +@@ -1208,7 +1210,7 @@ int sx1302_agc_status(uint8_t* status) { + + err = lgw_reg_r(SX1302_REG_AGC_MCU_MCU_AGC_STATUS_MCU_AGC_STATUS, &val); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: Failed to get AGC status\n"); ++ ERROR_PRINTF("Failed to get AGC status\n"); + return LGW_REG_ERROR; + } + +@@ -1240,13 +1242,13 @@ int sx1302_agc_mailbox_read(uint8_t mailbox, uint8_t* value) { + + /* Check parameters */ + if (mailbox > 3) { +- printf("ERROR: invalid AGC mailbox ID\n"); ++ ERROR_PRINTF("invalid AGC mailbox ID\n"); + return LGW_REG_ERROR; + } + + reg = SX1302_REG_AGC_MCU_MCU_MAIL_BOX_RD_DATA_BYTE0_MCU_MAIL_BOX_RD_DATA - mailbox; + if (lgw_reg_r(reg, &val) != LGW_REG_SUCCESS) { +- printf("ERROR: failed to read AGC mailbox\n"); ++ ERROR_PRINTF("failed to read AGC mailbox\n"); + return LGW_REG_ERROR; + } + +@@ -1262,13 +1264,13 @@ int sx1302_agc_mailbox_write(uint8_t mailbox, uint8_t value) { + + /* Check parameters */ + if (mailbox > 3) { +- printf("ERROR: invalid AGC mailbox ID\n"); ++ ERROR_PRINTF("invalid AGC mailbox ID\n"); + return LGW_REG_ERROR; + } + + reg = SX1302_REG_AGC_MCU_MCU_MAIL_BOX_WR_DATA_BYTE0_MCU_MAIL_BOX_WR_DATA - mailbox; + if (lgw_reg_w(reg, (int32_t)value) != LGW_REG_SUCCESS) { +- printf("ERROR: failed to write AGC mailbox\n"); ++ ERROR_PRINTF("failed to write AGC mailbox\n"); + return LGW_REG_ERROR; + } + +@@ -1278,14 +1280,14 @@ int sx1302_agc_mailbox_write(uint8_t mailbox, uint8_t value) { + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + + int sx1302_agc_start(uint8_t version, lgw_radio_type_t radio_type, uint8_t ana_gain, uint8_t dec_gain, bool full_duplex, bool lbt_enable) { +- uint8_t val; ++ uint8_t val = 0; + struct agc_gain_params_s agc_params; + uint8_t pa_start_delay; + uint8_t fdd_mode = ((full_duplex == true) ? 1 : 0); + + /* Check parameters */ + if ((radio_type != LGW_RADIO_TYPE_SX1255) && (radio_type != LGW_RADIO_TYPE_SX1257) && (radio_type != LGW_RADIO_TYPE_SX1250)) { +- DEBUG_MSG("ERROR: invalid radio type\n"); ++ ERROR_PRINTF("ERROR: invalid radio type\n"); + return LGW_REG_ERROR; + } + +@@ -1294,7 +1296,7 @@ int sx1302_agc_start(uint8_t version, lgw_radio_type_t radio_type, uint8_t ana_g + + sx1302_agc_mailbox_read(0, &val); + if (val != version) { +- printf("ERROR: wrong AGC fw version (%d)\n", val); ++ ERROR_PRINTF("wrong AGC fw version (%d)\n", val); + return LGW_REG_ERROR; + } + DEBUG_PRINTF("AGC FW VERSION: %d\n", val); +@@ -1305,7 +1307,7 @@ int sx1302_agc_start(uint8_t version, lgw_radio_type_t radio_type, uint8_t ana_g + sx1302_agc_mailbox_write(0, ana_gain); /* 0:auto agc*/ + sx1302_agc_mailbox_write(1, dec_gain); + if (radio_type != LGW_RADIO_TYPE_SX1250) { +- printf("AGC: setting fdd_mode to %u\n", fdd_mode); ++ DEBUG_PRINTF("AGC: setting fdd_mode to %u\n", fdd_mode); + sx1302_agc_mailbox_write(2, fdd_mode); + } + +@@ -1318,21 +1320,21 @@ int sx1302_agc_start(uint8_t version, lgw_radio_type_t radio_type, uint8_t ana_g + /* Check ana_gain setting */ + sx1302_agc_mailbox_read(0, &val); + if (val != ana_gain) { +- printf("ERROR: Analog gain of Radio A has not been set properly\n"); ++ ERROR_PRINTF("Analog gain of Radio A has not been set properly\n"); + return LGW_REG_ERROR; + } + + /* Check dec_gain setting */ + sx1302_agc_mailbox_read(1, &val); + if (val != dec_gain) { +- printf("ERROR: Decimator gain of Radio A has not been set properly\n"); ++ ERROR_PRINTF("Decimator gain of Radio A has not been set properly\n"); + return LGW_REG_ERROR; + } + + /* Check FDD mode setting */ + sx1302_agc_mailbox_read(2, &val); + if (val != fdd_mode) { +- printf("ERROR: FDD mode of Radio A has not been set properly\n"); ++ ERROR_PRINTF("FDD mode of Radio A has not been set properly\n"); + return LGW_REG_ERROR; + } + +@@ -1356,21 +1358,21 @@ int sx1302_agc_start(uint8_t version, lgw_radio_type_t radio_type, uint8_t ana_g + /* Check ana_gain setting */ + sx1302_agc_mailbox_read(0, &val); + if (val != ana_gain) { +- printf("ERROR: Analog gain of Radio B has not been set properly\n"); ++ ERROR_PRINTF("Analog gain of Radio B has not been set properly\n"); + return LGW_REG_ERROR; + } + + /* Check dec_gain setting */ + sx1302_agc_mailbox_read(1, &val); + if (val != dec_gain) { +- printf("ERROR: Decimator gain of Radio B has not been set properly\n"); ++ ERROR_PRINTF("Decimator gain of Radio B has not been set properly\n"); + return LGW_REG_ERROR; + } + + /* Check FDD mode setting */ + sx1302_agc_mailbox_read(2, &val); + if (val != fdd_mode) { +- printf("ERROR: FDD mode of Radio B has not been set properly\n"); ++ ERROR_PRINTF("FDD mode of Radio B has not been set properly\n"); + return LGW_REG_ERROR; + } + +@@ -1394,12 +1396,12 @@ int sx1302_agc_start(uint8_t version, lgw_radio_type_t radio_type, uint8_t ana_g + /* Check params */ + sx1302_agc_mailbox_read(0, &val); + if (val != agc_params.ana_min) { +- printf("ERROR: wrong ana_min (w:%u r:%u)\n", agc_params.ana_min, val); ++ ERROR_PRINTF("wrong ana_min (w:%u r:%u)\n", agc_params.ana_min, val); + return LGW_REG_ERROR; + } + sx1302_agc_mailbox_read(1, &val); + if (val != agc_params.ana_max) { +- printf("ERROR: ana_max (w:%u r:%u)\n", agc_params.ana_max, val); ++ ERROR_PRINTF("ana_max (w:%u r:%u)\n", agc_params.ana_max, val); + return LGW_REG_ERROR; + } + +@@ -1420,12 +1422,12 @@ int sx1302_agc_start(uint8_t version, lgw_radio_type_t radio_type, uint8_t ana_g + /* Check params */ + sx1302_agc_mailbox_read(0, &val); + if (val != agc_params.ana_thresh_l) { +- printf("ERROR: wrong ana_thresh_l (w:%u r:%u)\n", agc_params.ana_thresh_l, val); ++ ERROR_PRINTF("wrong ana_thresh_l (w:%u r:%u)\n", agc_params.ana_thresh_l, val); + return LGW_REG_ERROR; + } + sx1302_agc_mailbox_read(1, &val); + if (val != agc_params.ana_thresh_h) { +- printf("ERROR: wrong ana_thresh_h (w:%u r:%u)\n", agc_params.ana_thresh_h, val); ++ ERROR_PRINTF("wrong ana_thresh_h (w:%u r:%u)\n", agc_params.ana_thresh_h, val); + return LGW_REG_ERROR; + } + +@@ -1446,12 +1448,12 @@ int sx1302_agc_start(uint8_t version, lgw_radio_type_t radio_type, uint8_t ana_g + /* Check params */ + sx1302_agc_mailbox_read(0, &val); + if (val != agc_params.dec_attn_min) { +- printf("ERROR: wrong dec_attn_min (w:%u r:%u)\n", agc_params.dec_attn_min, val); ++ ERROR_PRINTF("wrong dec_attn_min (w:%u r:%u)\n", agc_params.dec_attn_min, val); + return LGW_REG_ERROR; + } + sx1302_agc_mailbox_read(1, &val); + if (val != agc_params.dec_attn_max) { +- printf("ERROR: wrong dec_attn_max (w:%u r:%u)\n", agc_params.dec_attn_max, val); ++ ERROR_PRINTF("wrong dec_attn_max (w:%u r:%u)\n", agc_params.dec_attn_max, val); + return LGW_REG_ERROR; + } + +@@ -1473,17 +1475,17 @@ int sx1302_agc_start(uint8_t version, lgw_radio_type_t radio_type, uint8_t ana_g + /* Check params */ + sx1302_agc_mailbox_read(0, &val); + if (val != agc_params.dec_thresh_l) { +- printf("ERROR: wrong dec_thresh_l (w:%u r:%u)\n", agc_params.dec_thresh_l, val); ++ ERROR_PRINTF("wrong dec_thresh_l (w:%u r:%u)\n", agc_params.dec_thresh_l, val); + return LGW_REG_ERROR; + } + sx1302_agc_mailbox_read(1, &val); + if (val != agc_params.dec_thresh_h1) { +- printf("ERROR: wrong dec_thresh_h1 (w:%u r:%u)\n", agc_params.dec_thresh_h1, val); ++ ERROR_PRINTF("wrong dec_thresh_h1 (w:%u r:%u)\n", agc_params.dec_thresh_h1, val); + return LGW_REG_ERROR; + } + sx1302_agc_mailbox_read(2, &val); + if (val != agc_params.dec_thresh_h2) { +- printf("ERROR: wrong dec_thresh_h2 (w:%u r:%u)\n", agc_params.dec_thresh_h2, val); ++ ERROR_PRINTF("wrong dec_thresh_h2 (w:%u r:%u)\n", agc_params.dec_thresh_h2, val); + return LGW_REG_ERROR; + } + +@@ -1504,12 +1506,12 @@ int sx1302_agc_start(uint8_t version, lgw_radio_type_t radio_type, uint8_t ana_g + /* Check params */ + sx1302_agc_mailbox_read(0, &val); + if (val != agc_params.chan_attn_min) { +- printf("ERROR: wrong chan_attn_min (w:%u r:%u)\n", agc_params.chan_attn_min, val); ++ ERROR_PRINTF("wrong chan_attn_min (w:%u r:%u)\n", agc_params.chan_attn_min, val); + return LGW_REG_ERROR; + } + sx1302_agc_mailbox_read(1, &val); + if (val != agc_params.chan_attn_max) { +- printf("ERROR: wrong chan_attn_max (w:%u r:%u)\n", agc_params.chan_attn_max, val); ++ ERROR_PRINTF("wrong chan_attn_max (w:%u r:%u)\n", agc_params.chan_attn_max, val); + return LGW_REG_ERROR; + } + +@@ -1530,12 +1532,12 @@ int sx1302_agc_start(uint8_t version, lgw_radio_type_t radio_type, uint8_t ana_g + /* Check params */ + sx1302_agc_mailbox_read(0, &val); + if (val != agc_params.chan_thresh_l) { +- printf("ERROR: wrong chan_thresh_l (w:%u r:%u)\n", agc_params.chan_thresh_l, val); ++ ERROR_PRINTF("wrong chan_thresh_l (w:%u r:%u)\n", agc_params.chan_thresh_l, val); + return LGW_REG_ERROR; + } + sx1302_agc_mailbox_read(1, &val); + if (val != agc_params.chan_thresh_h) { +- printf("ERROR: wrong chan_thresh_h (w:%u r:%u)\n", agc_params.chan_thresh_h, val); ++ ERROR_PRINTF("wrong chan_thresh_h (w:%u r:%u)\n", agc_params.chan_thresh_h, val); + return LGW_REG_ERROR; + } + +@@ -1558,17 +1560,17 @@ int sx1302_agc_start(uint8_t version, lgw_radio_type_t radio_type, uint8_t ana_g + /* Check params */ + sx1302_agc_mailbox_read(0, &val); + if (val != agc_params.deviceSel) { +- printf("ERROR: wrong deviceSel (w:%u r:%u)\n", agc_params.deviceSel, val); ++ ERROR_PRINTF("wrong deviceSel (w:%u r:%u)\n", agc_params.deviceSel, val); + return LGW_REG_ERROR; + } + sx1302_agc_mailbox_read(1, &val); + if (val != agc_params.hpMax) { +- printf("ERROR: wrong hpMax (w:%u r:%u)\n", agc_params.hpMax, val); ++ ERROR_PRINTF("wrong hpMax (w:%u r:%u)\n", agc_params.hpMax, val); + return LGW_REG_ERROR; + } + sx1302_agc_mailbox_read(2, &val); + if (val != agc_params.paDutyCycle) { +- printf("ERROR: wrong paDutyCycle (w:%u r:%u)\n", agc_params.paDutyCycle, val); ++ ERROR_PRINTF("wrong paDutyCycle (w:%u r:%u)\n", agc_params.paDutyCycle, val); + return LGW_REG_ERROR; + } + +@@ -1590,7 +1592,7 @@ int sx1302_agc_start(uint8_t version, lgw_radio_type_t radio_type, uint8_t ana_g + /* Check params */ + sx1302_agc_mailbox_read(0, &val); + if (val != pa_start_delay) { +- printf("ERROR: wrong PA start delay (w:%u r:%u)\n", pa_start_delay, val); ++ ERROR_PRINTF("wrong PA start delay (w:%u r:%u)\n", pa_start_delay, val); + return LGW_REG_ERROR; + } + +@@ -1610,7 +1612,7 @@ int sx1302_agc_start(uint8_t version, lgw_radio_type_t radio_type, uint8_t ana_g + /* Check params */ + sx1302_agc_mailbox_read(0, &val); + if ((bool)val != lbt_enable) { +- printf("ERROR: wrong LBT configuration (w:%u r:%u)\n", lbt_enable, val); ++ ERROR_PRINTF("wrong LBT configuration (w:%u r:%u)\n", lbt_enable, val); + return LGW_REG_ERROR; + } + +@@ -1644,7 +1646,7 @@ int sx1302_arb_load_firmware(const uint8_t *firmware) { + /* Read back and check */ + err |= lgw_mem_rb(ARB_MEM_ADDR, fw_check, MCU_FW_SIZE, false); + if (memcmp(firmware, fw_check, sizeof fw_check) != 0) { +- printf("ERROR: ARB fw read/write check failed\n"); ++ ERROR_PRINTF("ARB fw read/write check failed\n"); + return LGW_REG_ERROR; + } + +@@ -1654,7 +1656,7 @@ int sx1302_arb_load_firmware(const uint8_t *firmware) { + + err |= lgw_reg_r(SX1302_REG_ARB_MCU_CTRL_PARITY_ERROR, &val); + if (val != 0) { +- printf("ERROR: Failed to load ARB fw: parity error check failed\n"); ++ ERROR_PRINTF("Failed to load ARB fw: parity error check failed\n"); + return LGW_REG_ERROR; + } + DEBUG_MSG("ARB fw loaded\n"); +@@ -1670,7 +1672,7 @@ int sx1302_arb_status(uint8_t* status) { + + err = lgw_reg_r(SX1302_REG_ARB_MCU_MCU_ARB_STATUS_MCU_ARB_STATUS, &val); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: Failed to get ARB status\n"); ++ ERROR_PRINTF("Failed to get ARB status\n"); + return LGW_REG_ERROR; + } + +@@ -1702,13 +1704,13 @@ int sx1302_arb_debug_read(uint8_t reg_id, uint8_t* value) { + + /* Check parameters */ + if (reg_id > 15) { +- printf("ERROR: invalid ARB debug register ID\n"); ++ ERROR_PRINTF("invalid ARB debug register ID\n"); + return LGW_REG_ERROR; + } + + reg = SX1302_REG_ARB_MCU_ARB_DEBUG_STS_0_ARB_DEBUG_STS_0 + reg_id; + if (lgw_reg_r(reg, &val) != LGW_REG_SUCCESS) { +- printf("ERROR: failed to read ARB debug register\n"); ++ ERROR_PRINTF("failed to read ARB debug register\n"); + return LGW_REG_ERROR; + } + +@@ -1724,13 +1726,13 @@ int sx1302_arb_debug_write(uint8_t reg_id, uint8_t value) { + + /* Check parameters */ + if (reg_id > 3) { +- printf("ERROR: invalid ARB debug register ID\n"); ++ ERROR_PRINTF("invalid ARB debug register ID\n"); + return LGW_REG_ERROR; + } + + reg = SX1302_REG_ARB_MCU_ARB_DEBUG_CFG_0_ARB_DEBUG_CFG_0 + reg_id; + if (lgw_reg_w(reg, (int32_t)value) != LGW_REG_SUCCESS) { +- printf("ERROR: failed to write ARB debug register ID\n"); ++ ERROR_PRINTF("failed to write ARB debug register ID\n"); + return LGW_REG_ERROR; + } + +@@ -1754,7 +1756,7 @@ uint8_t sx1302_arb_get_debug_stats_detect(uint8_t channel) { + int32_t dbg_val; + + if (channel >= 8) { +- printf("ERROR: wrong configuration, channel num must be < 8"); ++ ERROR_PRINTF("wrong configuration, channel num must be < 8"); + return 0; + } + lgw_reg_r(SX1302_REG_ARB_MCU_ARB_DEBUG_STS_0_ARB_DEBUG_STS_0 + channel, &dbg_val); +@@ -1768,7 +1770,7 @@ uint8_t sx1302_arb_get_debug_stats_alloc(uint8_t channel) { + int32_t dbg_val; + + if (channel >= 8) { +- printf("ERROR: wrong configuration, channel num must be < 8"); ++ ERROR_PRINTF("wrong configuration, channel num must be < 8"); + return 0; + } + lgw_reg_r(SX1302_REG_ARB_MCU_ARB_DEBUG_STS_8_ARB_DEBUG_STS_8 + channel, &dbg_val); +@@ -1809,7 +1811,7 @@ void sx1302_arb_print_debug_stats(void) { + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + + int sx1302_arb_start(uint8_t version, const struct lgw_conf_ftime_s * ftime_context) { +- uint8_t val; ++ uint8_t val = 0; + + /* Wait for ARB fw to be started, and VERSION available in debug registers */ + sx1302_arb_wait_status(0x01); +@@ -1817,7 +1819,7 @@ int sx1302_arb_start(uint8_t version, const struct lgw_conf_ftime_s * ftime_cont + /* Get firmware VERSION */ + sx1302_arb_debug_read(0, &val); + if (val != version) { +- printf("ERROR: wrong ARB fw version (%d)\n", val); ++ ERROR_PRINTF("wrong ARB fw version (%d)\n", val); + return LGW_REG_ERROR; + } + DEBUG_PRINTF("ARB FW VERSION: %d\n", val); +@@ -1827,17 +1829,17 @@ int sx1302_arb_start(uint8_t version, const struct lgw_conf_ftime_s * ftime_cont + + /* Enable/Disable double demod for different timing set (best timestamp / best demodulation) - 1 bit per SF (LSB=SF5, MSB=SF12) => 0:Disable 1:Enable */ + if (ftime_context->enable == false) { +- printf("ARB: dual demodulation disabled for all SF\n"); ++ DEBUG_MSG("ARB: dual demodulation disabled for all SF\n"); + sx1302_arb_debug_write(3, 0x00); /* double demod disabled for all SF */ + } else { + if (ftime_context->mode == LGW_FTIME_MODE_ALL_SF) { +- printf("ARB: dual demodulation enabled for all SF\n"); ++ DEBUG_MSG("ARB: dual demodulation enabled for all SF\n"); + sx1302_arb_debug_write(3, 0xFF); /* double demod enabled for all SF */ + } else if (ftime_context->mode == LGW_FTIME_MODE_HIGH_CAPACITY) { +- printf("ARB: dual demodulation enabled for SF5 -> SF10\n"); ++ DEBUG_MSG("ARB: dual demodulation enabled for SF5 -> SF10\n"); + sx1302_arb_debug_write(3, 0x3F); /* double demod enabled for SF10 <- SF5 */ + } else { +- printf("ERROR: fine timestamp mode is not supported (%d)\n", ftime_context->mode); ++ ERROR_PRINTF("fine timestamp mode is not supported (%d)\n", ftime_context->mode); + return LGW_REG_ERROR; + } + } +@@ -1870,18 +1872,18 @@ int sx1302_fetch(uint8_t * nb_pkt) { + /* Initialize RX buffer */ + err = rx_buffer_new(&rx_buffer); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: Failed to initialize RX buffer\n"); ++ ERROR_PRINTF("Failed to initialize RX buffer\n"); + return LGW_REG_ERROR; + } + + /* Fetch RX buffer if any data available */ + err = rx_buffer_fetch(&rx_buffer); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: Failed to fetch RX buffer\n"); ++ ERROR_PRINTF("Failed to fetch RX buffer\n"); + return LGW_REG_ERROR; + } + } else { +- printf("Note: remaining %u packets in RX buffer, do not fetch sx1302 yet...\n", rx_buffer.buffer_pkt_nb); ++ DEBUG_PRINTF("Note: remaining %u packets in RX buffer, do not fetch sx1302 yet...\n", rx_buffer.buffer_pkt_nb); + } + + /* Return the number of packet fetched */ +@@ -1969,7 +1971,7 @@ int sx1302_parse(lgw_context_t * context, struct lgw_pkt_rx_s * p) { + if (p->size > 0) { + payload_crc16_calc = sx1302_lora_payload_crc(p->payload, p->size); + if (payload_crc16_calc != pkt.rx_crc16_value) { +- printf("ERROR: Payload CRC16 check failed (got:0x%04X calc:0x%04X)\n", pkt.rx_crc16_value, payload_crc16_calc); ++ ERROR_PRINTF("Payload CRC16 check failed (got:0x%04X calc:0x%04X)\n", pkt.rx_crc16_value, payload_crc16_calc); + if (log_file != NULL) { + fprintf(log_file, "ERROR: Payload CRC16 check failed (got:0x%04X calc:0x%04X)\n", pkt.rx_crc16_value, payload_crc16_calc); + dbg_log_buffer_to_file(log_file, rx_buffer.buffer, rx_buffer.buffer_size); +@@ -2064,7 +2066,7 @@ int sx1302_parse(lgw_context_t * context, struct lgw_pkt_rx_s * p) { + break; + default: + p->freq_offset = 0; +- printf("Invalid frequency offset\n"); ++ ERROR_PRINTF("Invalid frequency offset\n"); + break; + } + +@@ -2106,10 +2108,10 @@ int sx1302_parse(lgw_context_t * context, struct lgw_pkt_rx_s * p) { + if (pkt.crc_en) { + /* CRC enabled */ + if (pkt.payload_crc_error) { +- printf("FSK: CRC ERR\n"); ++ DEBUG_MSG("FSK: CRC ERR\n"); + p->status = STAT_CRC_BAD; + } else { +- printf("FSK: CRC OK\n"); ++ DEBUG_MSG("FSK: CRC OK\n"); + p->status = STAT_CRC_OK; + } + } else { +@@ -2132,7 +2134,7 @@ int sx1302_parse(lgw_context_t * context, struct lgw_pkt_rx_s * p) { + p->snr = -128.0; + p->rssis = -128.0; + } else { +- DEBUG_MSG("ERROR: UNEXPECTED PACKET ORIGIN\n"); ++ ERROR_PRINTF("UNEXPECTED PACKET ORIGIN\n"); + p->status = STAT_UNDEFINED; + p->modulation = MOD_UNDEFINED; + p->rssic = -128.0; +@@ -2215,7 +2217,7 @@ int sx1302_tx_set_start_delay(uint8_t rf_chain, lgw_radio_type_t radio_type, uin + + /* tx start delay only necessary for beaconing (LoRa) */ + if (modulation != MOD_LORA) { +- *delay = 0; ++ *delay = tx_start_delay; + return LGW_REG_SUCCESS; + } + +@@ -2229,7 +2231,7 @@ int sx1302_tx_set_start_delay(uint8_t rf_chain, lgw_radio_type_t radio_type, uin + } else if (bandwidth == BW_500KHZ) { + radio_bw_delay = 21; + } else { +- DEBUG_MSG("ERROR: bandwidth not supported\n"); ++ ERROR_PRINTF("ERROR: bandwidth not supported\n"); + return LGW_REG_ERROR; + } + break; +@@ -2243,12 +2245,12 @@ int sx1302_tx_set_start_delay(uint8_t rf_chain, lgw_radio_type_t radio_type, uin + } else if (bandwidth == BW_500KHZ) { + radio_bw_delay += 0; + } else { +- DEBUG_MSG("ERROR: bandwidth not supported\n"); ++ ERROR_PRINTF("ERROR: bandwidth not supported\n"); + return LGW_REG_ERROR; + } + break; + default: +- DEBUG_MSG("ERROR: radio type not supported\n"); ++ ERROR_PRINTF("ERROR: radio type not supported\n"); + return LGW_REG_ERROR; + } + +@@ -2300,7 +2302,7 @@ uint8_t sx1302_tx_status(uint8_t rf_chain) { + + err = lgw_reg_r(SX1302_REG_TX_TOP_TX_FSM_STATUS_TX_STATUS(rf_chain), &read_value); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: Failed to read TX STATUS\n"); ++ ERROR_PRINTF("Failed to read TX STATUS\n"); + return TX_STATUS_UNKNOWN; + } + +@@ -2311,7 +2313,7 @@ uint8_t sx1302_tx_status(uint8_t rf_chain) { + } else if ((read_value == 0x91) || (read_value == 0x92)) { + return TX_SCHEDULED; + } else { +- printf("ERROR: UNKNOWN TX STATUS 0x%02X\n", read_value); ++ ERROR_PRINTF("UNKNOWN TX STATUS 0x%02X\n", read_value); + return TX_STATUS_UNKNOWN; + } + } +@@ -2335,7 +2337,7 @@ int sx1302_tx_abort(uint8_t rf_chain) { + err |= lgw_reg_w(SX1302_REG_TX_TOP_TX_TRIG_TX_TRIG_DELAYED(rf_chain), 0x00); + err |= lgw_reg_w(SX1302_REG_TX_TOP_TX_TRIG_TX_TRIG_GPS(rf_chain), 0x00); + if (err != LGW_REG_SUCCESS) { +- printf("ERROR: Failed to stop TX trigger\n"); ++ ERROR_PRINTF("Failed to stop TX trigger\n"); + return err; + } + +@@ -2343,7 +2345,7 @@ int sx1302_tx_abort(uint8_t rf_chain) { + do { + /* handle timeout */ + if (timeout_check(tm_start, 1000) != 0) { +- printf("ERROR: %s: TIMEOUT on TX abort\n", __FUNCTION__); ++ ERROR_PRINTF("TIMEOUT on TX abort\n"); + return LGW_REG_ERROR; + } + +@@ -2378,7 +2380,7 @@ int sx1302_tx_configure(lgw_radio_type_t radio_type) { + err |= lgw_reg_w(SX1302_REG_TX_TOP_B_TX_RFFE_IF_CTRL_TX_IF_DST, 0x00); + break; + default: +- DEBUG_MSG("ERROR: radio type not supported\n"); ++ ERROR_PRINTF("ERROR: radio type not supported\n"); + return LGW_REG_ERROR; + } + +@@ -2476,7 +2478,7 @@ int sx1302_send(lgw_radio_type_t radio_type, struct lgw_tx_gain_lut_s * tx_lut, + power = (tx_lut->lut[pow_index].pa_gain << 6) | (tx_lut->lut[pow_index].dac_gain << 4) | tx_lut->lut[pow_index].mix_gain; + break; + default: +- DEBUG_MSG("ERROR: radio type not supported\n"); ++ ERROR_PRINTF("ERROR: radio type not supported\n"); + return LGW_REG_ERROR; + } + err = lgw_reg_w(SX1302_REG_TX_TOP_AGC_TX_PWR_AGC_TX_PWR(pkt_data->rf_chain), power); +@@ -2509,7 +2511,7 @@ int sx1302_send(lgw_radio_type_t radio_type, struct lgw_tx_gain_lut_s * tx_lut, + mod_bw = (0x01 << 7) | pkt_data->bandwidth; + break; + default: +- printf("ERROR: Modulation not supported\n"); ++ ERROR_PRINTF("Modulation not supported\n"); + return LGW_REG_ERROR; + } + err = lgw_reg_w(SX1302_REG_TX_TOP_AGC_TX_BW_AGC_TX_BW(pkt_data->rf_chain), mod_bw); +@@ -2520,7 +2522,7 @@ int sx1302_send(lgw_radio_type_t radio_type, struct lgw_tx_gain_lut_s * tx_lut, + case MOD_CW: + /* Set frequency deviation */ + freq_dev = ceil(fabs( (float)pkt_data->freq_offset / 10) ) * 10e3; +- printf("CW: f_dev %d Hz\n", (int)(freq_dev)); ++ DEBUG_PRINTF("CW: f_dev %d Hz\n", (int)(freq_dev)); + fdev_reg = SX1302_FREQ_TO_REG(freq_dev); + err = lgw_reg_w(SX1302_REG_TX_TOP_TX_RFFE_IF_FREQ_DEV_H_FREQ_DEV(pkt_data->rf_chain), (fdev_reg >> 8) & 0xFF); + CHECK_ERR(err); +@@ -2537,7 +2539,7 @@ int sx1302_send(lgw_radio_type_t radio_type, struct lgw_tx_gain_lut_s * tx_lut, + CHECK_ERR(err); + + /* Set the frequency offset (ratio of the frequency deviation)*/ +- printf("CW: IF test mod freq %d\n", (int)(((float)pkt_data->freq_offset*1e3*64/(float)freq_dev))); ++ DEBUG_PRINTF("CW: IF test mod freq %d\n", (int)(((float)pkt_data->freq_offset*1e3*64/(float)freq_dev))); + err = lgw_reg_w(SX1302_REG_TX_TOP_TX_RFFE_IF_TEST_MOD_FREQ(pkt_data->rf_chain), (int)(((float)pkt_data->freq_offset*1e3*64/(float)freq_dev))); + CHECK_ERR(err); + break; +@@ -2721,7 +2723,7 @@ int sx1302_send(lgw_radio_type_t radio_type, struct lgw_tx_gain_lut_s * tx_lut, + CHECK_ERR(err); + break; + default: +- printf("ERROR: Modulation not supported\n"); ++ ERROR_PRINTF("Modulation not supported\n"); + return LGW_REG_ERROR; + } + +@@ -2779,7 +2781,7 @@ int sx1302_send(lgw_radio_type_t radio_type, struct lgw_tx_gain_lut_s * tx_lut, + CHECK_ERR(err); + break; + default: +- printf("ERROR: TX mode not supported\n"); ++ ERROR_PRINTF("TX mode not supported\n"); + return LGW_REG_ERROR; + } + +diff --git a/libloragw/src/loragw_sx1302_rx.c b/libloragw/src/loragw_sx1302_rx.c +index 5f15129..df90d67 100644 +--- a/libloragw/src/loragw_sx1302_rx.c ++++ b/libloragw/src/loragw_sx1302_rx.c +@@ -40,6 +40,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + #define CHECK_NULL(a) if(a==NULL){return LGW_REG_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + #define SX1302_PKT_PAYLOAD_LENGTH(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 2], 0, 8) + #define SX1302_PKT_CHANNEL(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 3], 0, 8) + #define SX1302_PKT_CRC_EN(buffer, start_index) TAKE_N_BITS_FROM(buffer[start_index + 4], 0, 1) +@@ -127,7 +129,7 @@ int rx_buffer_del(rx_buffer_t * self) { + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + + int rx_buffer_fetch(rx_buffer_t * self) { +- int i, res; ++ int res; + uint8_t buff[2]; + uint8_t payload_len; + uint16_t next_pkt_idx; +@@ -155,20 +157,16 @@ int rx_buffer_fetch(rx_buffer_t * self) { + memset(self->buffer, 0, sizeof self->buffer); + res = lgw_mem_rb(0x4000, self->buffer, self->buffer_size, true); + if (res != LGW_REG_SUCCESS) { +- printf("ERROR: Failed to read RX buffer, SPI error\n"); ++ ERROR_PRINTF("Failed to read RX buffer, SPI error\n"); + return LGW_REG_ERROR; + } + + /* print debug info */ +- DEBUG_MSG("RX_BUFFER: "); +- for (i = 0; i < self->buffer_size; i++) { +- DEBUG_PRINTF("%02X ", self->buffer[i]); +- } +- DEBUG_MSG("\n"); ++ DEBUG_PRINTF("RX BUFFER: %H ", self->buffer_size, self->buffer); + + /* Sanity check: is there at least 1 complete packet in the buffer */ + if (self->buffer_size < (SX1302_PKT_HEAD_METADATA + SX1302_PKT_TAIL_METADATA)) { +- printf("WARNING: not enough data to have a complete packet, discard rx_buffer\n"); ++ DEBUG_MSG("WARNING: not enough data to have a complete packet, discard rx_buffer\n"); + return rx_buffer_del(self); + } + +@@ -179,16 +177,16 @@ int rx_buffer_fetch(rx_buffer_t * self) { + DEBUG_PRINTF("INFO: syncword found at idx %d\n", idx); + break; + } else { +- printf("INFO: syncword not found at idx %d\n", idx); ++ DEBUG_PRINTF("INFO: syncword not found at idx %d\n", idx); + idx += 1; + } + } + if (idx > self->buffer_size - 2) { +- printf("WARNING: no syncword found, discard rx_buffer\n"); ++ DEBUG_MSG("WARNING: no syncword found, discard rx_buffer\n"); + return rx_buffer_del(self); + } + if (idx != 0) { +- printf("INFO: re-sync rx_buffer at idx %d\n", idx); ++ DEBUG_PRINTF("INFO: re-sync rx_buffer at idx %d\n", idx); + memmove((void *)(self->buffer), (void *)(self->buffer + idx), self->buffer_size - idx); + self->buffer_size -= idx; + } +@@ -197,7 +195,7 @@ int rx_buffer_fetch(rx_buffer_t * self) { + idx = 0; + while (idx < self->buffer_size) { + if ((self->buffer[idx] != SX1302_PKT_SYNCWORD_BYTE_0) || (self->buffer[idx + 1] != SX1302_PKT_SYNCWORD_BYTE_1)) { +- printf("WARNING: syncword not found at idx %d, discard the rx_buffer\n", idx); ++ DEBUG_PRINTF("WARNING: syncword not found at idx %d, discard the rx_buffer\n", idx); + return rx_buffer_del(self); + } + /* One packet found in the buffer */ +@@ -256,7 +254,7 @@ int rx_buffer_pop(rx_buffer_t * self, rx_packet_t * pkt) { + + /* Check if we have a complete packet in the rx buffer fetched */ + if((self->buffer_index + pkt_num_bytes) > self->buffer_size) { +- printf("WARNING: aborting truncated message (size=%u)\n", self->buffer_size); ++ DEBUG_PRINTF("WARNING: aborting truncated message (size=%u)\n", self->buffer_size); + return LGW_REG_WARNING; + } + +@@ -271,7 +269,7 @@ int rx_buffer_pop(rx_buffer_t * self, rx_packet_t * pkt) { + + /* Check if the checksum is correct */ + if (checksum_rcv != checksum_calc) { +- printf("WARNING: checksum failed (got:0x%02X calc:0x%02X)\n", checksum_rcv, checksum_calc); ++ DEBUG_PRINTF("WARNING: checksum failed (got:0x%02X calc:0x%02X)\n", checksum_rcv, checksum_calc); + return LGW_REG_WARNING; + } else { + DEBUG_PRINTF("Packet checksum OK (0x%02X)\n", checksum_rcv); +@@ -334,16 +332,16 @@ int rx_buffer_pop(rx_buffer_t * self, rx_packet_t * pkt) { + + /* Sanity checks: check the range of few metadata */ + if (pkt->modem_id > SX1302_FSK_MODEM_ID) { +- printf("ERROR: modem_id is out of range - %u\n", pkt->modem_id); ++ ERROR_PRINTF("modem_id is out of range - %u\n", pkt->modem_id); + return LGW_REG_ERROR; + } else { + if (pkt->modem_id <= SX1302_LORA_STD_MODEM_ID) { /* LoRa modems */ + if (pkt->rx_channel_in > 9) { +- printf("ERROR: channel is out of range - %u\n", pkt->rx_channel_in); ++ ERROR_PRINTF("channel is out of range - %u\n", pkt->rx_channel_in); + return LGW_REG_ERROR; + } + if ((pkt->rx_rate_sf < 5) || (pkt->rx_rate_sf > 12)) { +- printf("ERROR: SF is out of range - %u\n", pkt->rx_rate_sf); ++ ERROR_PRINTF("SF is out of range - %u\n", pkt->rx_rate_sf); + return LGW_REG_ERROR; + } + } else { /* FSK modem */ +diff --git a/libloragw/src/loragw_sx1302_timestamp.c b/libloragw/src/loragw_sx1302_timestamp.c +index effeaa0..40c3144 100644 +--- a/libloragw/src/loragw_sx1302_timestamp.c ++++ b/libloragw/src/loragw_sx1302_timestamp.c +@@ -46,6 +46,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + #define CHECK_NULL(a) if(a==NULL){return LGW_REG_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE TYPES -------------------------------------------------------- */ + +@@ -121,7 +123,7 @@ int32_t legacy_timestamp_correction(uint8_t bandwidth, uint8_t sf, uint8_t cr, b + bw_pow = 4; + break; + default: +- printf("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT - %s\n", bandwidth, __FUNCTION__); ++ ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", bandwidth); + return 0; + } + +@@ -188,13 +190,13 @@ int32_t legacy_timestamp_correction(uint8_t bandwidth, uint8_t sf, uint8_t cr, b + total_delay = (filtering_delay + fft_delay_state3 + fft_delay + demap_delay + decode_delay + 500E3) / 1E6; + + if (total_delay > INT32_MAX) { +- printf("ERROR: overflow error for timestamp correction (SHOULD NOT HAPPEN)\n"); +- printf("=> filtering_delay %" PRIu64 "\n", filtering_delay); +- printf("=> fft_delay_state3 %" PRIu64 "\n", fft_delay_state3); +- printf("=> fft_delay %" PRIu64 "\n", fft_delay); +- printf("=> demap_delay %" PRIu64 "\n", demap_delay); +- printf("=> decode_delay %" PRIu64 "\n", decode_delay); +- printf("=> total_delay %" PRIu64 "\n", total_delay); ++ ERROR_PRINTF("overflow error for timestamp correction (SHOULD NOT HAPPEN)\n"); ++ ERROR_PRINTF("=> filtering_delay %" PRIu64 "\n", filtering_delay); ++ ERROR_PRINTF("=> fft_delay_state3 %" PRIu64 "\n", fft_delay_state3); ++ ERROR_PRINTF("=> fft_delay %" PRIu64 "\n", fft_delay); ++ ERROR_PRINTF("=> demap_delay %" PRIu64 "\n", demap_delay); ++ ERROR_PRINTF("=> decode_delay %" PRIu64 "\n", decode_delay); ++ ERROR_PRINTF("=> total_delay %" PRIu64 "\n", total_delay); + assert(0); + } + +@@ -231,7 +233,7 @@ int32_t precision_timestamp_correction(uint8_t bandwidth, uint8_t datarate, uint + bw_pow = 4; + break; + default: +- printf("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT - %s\n", bandwidth, __FUNCTION__); ++ ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", bandwidth); + return 0; + } + +@@ -240,7 +242,7 @@ int32_t precision_timestamp_correction(uint8_t bandwidth, uint8_t datarate, uint + /* NOTE: no need of the preamble size, only the payload duration is needed */ + /* WARNING: implicit header not supported */ + if (lora_packet_time_on_air(bandwidth, datarate, coderate, 0, false, !crc_en, payload_length, NULL, &nb_symbols_payload, &t_symbol_us) == 0) { +- printf("ERROR: failed to compute packet time on air - %s\n", __FUNCTION__); ++ ERROR_PRINTF("failed to compute packet time on air\n"); + return 0; + } + +@@ -300,21 +302,18 @@ void timestamp_counter_delete(timestamp_counter_t * self) { + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + + void timestamp_counter_update(timestamp_counter_t * self, uint32_t pps, uint32_t inst) { +- //struct timestamp_info_s* tinfo = (pps == true) ? &self->pps : &self->inst; +- +- /* Check if counter has wrapped, and update wrap status if necessary */ +- if (pps < self->pps.counter_us_27bits_ref) { +- self->pps.counter_us_27bits_wrap += 1; +- self->pps.counter_us_27bits_wrap %= 32; +- } + if (inst < self->inst.counter_us_27bits_ref) { + self->inst.counter_us_27bits_wrap += 1; + self->inst.counter_us_27bits_wrap %= 32; + } +- +- /* Update counter reference */ +- self->pps.counter_us_27bits_ref = pps; + self->inst.counter_us_27bits_ref = inst; ++ ++ if (self->pps.counter_us_27bits_ref != pps) { ++ uint32_t inst32 = self->inst.counter_us_27bits_ref | (self->inst.counter_us_27bits_wrap<<27); ++ inst32 += (int32_t)((pps - inst)<<5) >> 5; // 27bit signed diff (extend sign over top 5 bits) ++ self->pps.counter_us_27bits_ref = inst32 & ((1<<27)-1); ++ self->pps.counter_us_27bits_wrap = inst32 >> 27; ++ } + } + + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +@@ -332,7 +331,7 @@ int timestamp_counter_get(timestamp_counter_t * self, uint32_t * inst, uint32_t + */ + x = lgw_reg_rb(SX1302_REG_TIMESTAMP_TIMESTAMP_PPS_MSB2_TIMESTAMP_PPS, &buff[0], 8); + if (x != LGW_REG_SUCCESS) { +- printf("ERROR: Failed to get timestamp counter value\n"); ++ ERROR_PRINTF("Failed to get timestamp counter value\n"); + return -1; + } + +@@ -342,13 +341,13 @@ int timestamp_counter_get(timestamp_counter_t * self, uint32_t * inst, uint32_t + */ + x = lgw_reg_rb(SX1302_REG_TIMESTAMP_TIMESTAMP_PPS_MSB2_TIMESTAMP_PPS, &buff_wa[0], 8); + if (x != LGW_REG_SUCCESS) { +- printf("ERROR: Failed to get timestamp counter MSB value\n"); ++ ERROR_PRINTF("Failed to get timestamp counter MSB value\n"); + return -1; + } + if ((buff[0] != buff_wa[0]) || (buff[4] != buff_wa[4])) { + x = lgw_reg_rb(SX1302_REG_TIMESTAMP_TIMESTAMP_PPS_MSB2_TIMESTAMP_PPS, &buff_wa[0], 8); + if (x != LGW_REG_SUCCESS) { +- printf("ERROR: Failed to get timestamp counter MSB value\n"); ++ ERROR_PRINTF("Failed to get timestamp counter MSB value\n"); + return -1; + } + memcpy(buff, buff_wa, 8); /* use the new read value */ +@@ -429,11 +428,11 @@ int timestamp_counter_mode(bool ftime_enable) { + int x = LGW_REG_SUCCESS; + + if (ftime_enable == false) { +- printf("INFO: using legacy timestamp\n"); ++ INFO_PRINTF("using legacy timestamp\n"); + /* Latch end-of-packet timestamp (sx1301 compatibility) */ + x |= lgw_reg_w(SX1302_REG_RX_TOP_RX_BUFFER_LEGACY_TIMESTAMP, 0x01); + } else { +- printf("INFO: using precision timestamp (max_ts_metrics:%u nb_symbols:%u)\n", PRECISION_TIMESTAMP_TS_METRICS_MAX, PRECISION_TIMESTAMP_NB_SYMBOLS); ++ INFO_PRINTF("using precision timestamp (max_ts_metrics:%u nb_symbols:%u)\n", PRECISION_TIMESTAMP_TS_METRICS_MAX, PRECISION_TIMESTAMP_NB_SYMBOLS); + + /* Latch end-of-preamble timestamp */ + x |= lgw_reg_w(SX1302_REG_RX_TOP_RX_BUFFER_LEGACY_TIMESTAMP, 0x00); +@@ -453,15 +452,15 @@ int32_t timestamp_counter_correction(lgw_context_t * context, uint8_t bandwidth, + /* Check input parameters */ + CHECK_NULL(context); + if (IS_LORA_DR(datarate) == false) { +- printf("ERROR: wrong datarate (%u) - %s\n", datarate, __FUNCTION__); ++ ERROR_PRINTF("wrong datarate (%u)\n", datarate); + return 0; + } + if (IS_LORA_BW(bandwidth) == false) { +- printf("ERROR: wrong bandwidth (%u) - %s\n", bandwidth, __FUNCTION__); ++ ERROR_PRINTF("wrong bandwidth (%u)\n", bandwidth); + return 0; + } + if (IS_LORA_CR(coderate) == false) { +- printf("ERROR: wrong coding rate (%u) - %s\n", coderate, __FUNCTION__); ++ ERROR_PRINTF("wrong coding rate (%u)\n", coderate); + return 0; + } + +@@ -496,7 +495,7 @@ int precise_timestamp_calculate(uint8_t ts_metrics_nb, const int8_t * ts_metrics + + /* Check if we can calculate a ftime */ + if (timestamp_pps_history.size < MAX_TIMESTAMP_PPS_HISTORY) { +- printf("INFO: Cannot compute ftime yet, PPS history is too short\n"); ++ INFO_PRINTF("Cannot compute ftime yet, PPS history is too short\n"); + return -1; + } + +@@ -551,7 +550,7 @@ int precise_timestamp_calculate(uint8_t ts_metrics_nb, const int8_t * ts_metrics + /* Find the last timestamp_pps before packet to use as reference for ftime */ + x = lgw_reg_rb(SX1302_REG_TIMESTAMP_TIMESTAMP_PPS_MSB2_TIMESTAMP_PPS , &buff[0], 4); + if (x != LGW_REG_SUCCESS) { +- printf("ERROR: Failed to get timestamp counter value\n"); ++ ERROR_PRINTF("Failed to get timestamp counter value\n"); + return 0; + } + timestamp_pps_reg = (uint32_t)((buff[0] << 24) & 0xFF000000); +@@ -574,7 +573,7 @@ int precise_timestamp_calculate(uint8_t ts_metrics_nb, const int8_t * ts_metrics + } + } + if (timestamp_pps_idx == timestamp_pps_history.size) { +- printf("ERROR: failed to find the reference timestamp_pps, cannot compute ftime\n"); ++ ERROR_PRINTF("failed to find the reference timestamp_pps, cannot compute ftime\n"); + return -1; + } + +@@ -596,7 +595,7 @@ int precise_timestamp_calculate(uint8_t ts_metrics_nb, const int8_t * ts_metrics + + /* Sanity Check on xtal_correct */ + if ((xtal_correct > 1.2) || (xtal_correct < 0.8)) { +- printf("ERROR: xtal_error is invalid (%.15lf)\n", xtal_correct); ++ ERROR_PRINTF("xtal_error is invalid (%.15lf)\n", xtal_correct); + return -1; + } + +@@ -622,7 +621,7 @@ int precise_timestamp_calculate(uint8_t ts_metrics_nb, const int8_t * ts_metrics + + *result_ftime = (uint32_t)pkt_ftime; + if (*result_ftime > 1E9) { +- printf("ERROR: fine timestamp is out of range (%u)\n", *result_ftime); ++ ERROR_PRINTF("fine timestamp is out of range (%u)\n", *result_ftime); + return -1; + } + +diff --git a/libloragw/src/loragw_usb.c b/libloragw/src/loragw_usb.c +index 4fe7e9a..b69f73c 100644 +--- a/libloragw/src/loragw_usb.c ++++ b/libloragw/src/loragw_usb.c +@@ -47,6 +47,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + #define CHECK_NULL(a) if(a==NULL){return LGW_USB_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + +@@ -69,7 +71,7 @@ int set_interface_attribs_linux(int fd, int speed) { + + /* Get current attributes */ + if (tcgetattr(fd, &tty) != 0) { +- DEBUG_PRINTF("ERROR: tcgetattr failed with %d - %s", errno, strerror(errno)); ++ ERROR_PRINTF("tcgetattr failed with %d - %s", errno, strerror(errno)); + return LGW_USB_ERROR; + } + +@@ -96,7 +98,7 @@ int set_interface_attribs_linux(int fd, int speed) { + + /* Set attributes */ + if (tcsetattr(fd, TCSANOW, &tty) != 0) { +- DEBUG_PRINTF("ERROR: tcsetattr failed with %d - %s", errno, strerror(errno)); ++ ERROR_PRINTF("tcsetattr failed with %d - %s", errno, strerror(errno)); + return LGW_USB_ERROR; + } + +@@ -113,7 +115,7 @@ int set_blocking_linux(int fd, bool blocking) { + + /* Get current attributes */ + if (tcgetattr(fd, &tty) != 0) { +- DEBUG_PRINTF("ERROR: tcgetattr failed with %d - %s", errno, strerror(errno)); ++ ERROR_PRINTF("tcgetattr failed with %d - %s", errno, strerror(errno)); + return LGW_USB_ERROR; + } + +@@ -122,7 +124,7 @@ int set_blocking_linux(int fd, bool blocking) { + + /* Set attributes */ + if (tcsetattr(fd, TCSANOW, &tty) != 0) { +- DEBUG_PRINTF("ERROR: tcsetattr failed with %d - %s", errno, strerror(errno)); ++ ERROR_PRINTF("tcsetattr failed with %d - %s", errno, strerror(errno)); + return LGW_USB_ERROR; + } + +@@ -147,7 +149,7 @@ int lgw_usb_open(const char * com_path, void **com_target_ptr) { + + usb_device = malloc(sizeof(int)); + if (usb_device == NULL) { +- DEBUG_MSG("ERROR : MALLOC FAIL\n"); ++ ERROR_PRINTF("MALLOC FAIL\n"); + return LGW_USB_ERROR; + } + +@@ -155,18 +157,18 @@ int lgw_usb_open(const char * com_path, void **com_target_ptr) { + sprintf(portname, "%s", com_path); + fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC); + if (fd < 0) { +- printf("ERROR: failed to open COM port %s - %s\n", portname, strerror(errno)); ++ ERROR_PRINTF("failed to open COM port %s - %s\n", portname, strerror(errno)); + } else { +- printf("INFO: Configuring TTY\n"); ++ INFO_PRINTF("INFO: Configuring TTY\n"); + x = set_interface_attribs_linux(fd, B115200); + if (x != 0) { +- printf("ERROR: failed to configure COM port %s\n", portname); ++ ERROR_PRINTF("failed to configure COM port %s\n", portname); + free(usb_device); + return LGW_USB_ERROR; + } + + /* flush tty port before setting it as blocking */ +- printf("INFO: Flushing TTY\n"); ++ INFO_PRINTF("INFO: Flushing TTY\n"); + do { + n = read(fd, &data, 1); + if (n > 0) { +@@ -175,10 +177,10 @@ int lgw_usb_open(const char * com_path, void **com_target_ptr) { + } while (n > 0); + + /* set tty port blocking */ +- printf("INFO: Setting TTY in blocking mode\n"); ++ INFO_PRINTF("INFO: Setting TTY in blocking mode\n"); + x = set_blocking_linux(fd, true); + if (x != 0) { +- printf("ERROR: failed to configure COM port %s\n", portname); ++ ERROR_PRINTF("failed to configure COM port %s\n", portname); + free(usb_device); + return LGW_USB_ERROR; + } +@@ -187,25 +189,25 @@ int lgw_usb_open(const char * com_path, void **com_target_ptr) { + *com_target_ptr = (void*)usb_device; + + /* Initialize pseudo-random generator for MCU request ID */ +- srand(0); ++ // srand(0); + + /* Check MCU version (ignore first char of the received version (release/debug) */ +- printf("INFO: Connect to MCU\n"); ++ INFO_PRINTF("INFO: Connect to MCU\n"); + if (mcu_ping(fd, &gw_info) != 0) { +- printf("ERROR: failed to ping the concentrator MCU\n"); ++ ERROR_PRINTF("failed to ping the concentrator MCU\n"); + return LGW_USB_ERROR; + } + if (strncmp(gw_info.version + 1, mcu_version_string, sizeof mcu_version_string) != 0) { + printf("WARNING: MCU version mismatch (expected:%s, got:%s)\n", mcu_version_string, gw_info.version); + } +- printf("INFO: Concentrator MCU version is %s\n", gw_info.version); ++ INFO_PRINTF("INFO: Concentrator MCU version is %s\n", gw_info.version); + + /* Get MCU status */ + if (mcu_get_status(fd, &mcu_status) != 0) { +- printf("ERROR: failed to get status from the concentrator MCU\n"); ++ ERROR_PRINTF("failed to get status from the concentrator MCU\n"); + return LGW_USB_ERROR; + } +- printf("INFO: MCU status: sys_time:%u temperature:%.1foC\n", mcu_status.system_time_ms, mcu_status.temperature); ++ INFO_PRINTF("INFO: MCU status: sys_time:%u temperature:%.1foC\n", mcu_status.system_time_ms, mcu_status.temperature); + + /* Reset SX1302 */ + x = mcu_gpio_write(fd, 0, 1, 1); /* set PA1 : POWER_EN */ +@@ -215,7 +217,7 @@ int lgw_usb_open(const char * com_path, void **com_target_ptr) { + x |= mcu_gpio_write(fd, 0, 8, 0); /* set PA8 : SX1261_NRESET active */ + x |= mcu_gpio_write(fd, 0, 8, 1); /* unset PA8 : SX1261_NRESET inactive */ + if (x != 0) { +- printf("ERROR: failed to reset SX1302\n"); ++ ERROR_PRINTF("failed to reset SX1302\n"); + free(usb_device); + return LGW_USB_ERROR; + } +@@ -247,7 +249,7 @@ int lgw_usb_close(void *com_target) { + x |= mcu_gpio_write(usb_device, 0, 8, 0); /* set PA8 : SX1261_NRESET active */ + x |= mcu_gpio_write(usb_device, 0, 8, 1); /* unset PA8 : SX1261_NRESET inactive */ + if (x != 0) { +- printf("ERROR: failed to reset SX1302\n"); ++ ERROR_PRINTF("failed to reset SX1302\n"); + err = LGW_USB_ERROR; + } + +@@ -255,16 +257,16 @@ int lgw_usb_close(void *com_target) { + x = close(usb_device); + free(com_target); + if (x != 0) { +- printf("ERROR: failed to close USB file\n"); ++ ERROR_PRINTF("failed to close USB file\n"); + err = LGW_USB_ERROR; + } + + /* determine return code */ + if (err != 0) { +- printf("ERROR: USB PORT FAILED TO CLOSE\n"); ++ ERROR_PRINTF("USB PORT FAILED TO CLOSE\n"); + return LGW_USB_ERROR; + } else { +- DEBUG_MSG("Note: USB port closed\n"); ++ INFO_PRINTF("Note: USB port closed\n"); + return LGW_USB_SUCCESS; + } + } +@@ -316,10 +318,10 @@ int lgw_usb_rmw(void *com_target, uint16_t address, uint8_t offs, uint8_t leng, + + /* determine return code */ + if (a != 0) { +- DEBUG_MSG("ERROR: USB WRITE FAILURE\n"); ++ ERROR_PRINTF("USB WRITE FAILURE\n"); + return -1; + } else { +- DEBUG_MSG("Note: USB write success\n"); ++ // DEBUG_MSG("Note: USB write success\n"); + return 0; + } + } +@@ -364,10 +366,10 @@ int lgw_usb_wb(void *com_target, uint8_t spi_mux_target, uint16_t address, const + + /* determine return code */ + if (a != 0) { +- DEBUG_MSG("ERROR: USB WRITE BURST FAILURE\n"); ++ ERROR_PRINTF("USB WRITE BURST FAILURE\n"); + return -1; + } else { +- DEBUG_MSG("Note: USB write burst success\n"); ++ // DEBUG_MSG("Note: USB write burst success\n"); + return 0; + } + } +@@ -406,7 +408,7 @@ int lgw_usb_rb(void *com_target, uint8_t spi_mux_target, uint16_t address, uint8 + + if (_lgw_write_mode == LGW_COM_WRITE_MODE_BULK) { + /* makes no sense to read in bulk mode, as we can't get the result */ +- printf("ERROR: USB READ BURST FAILURE - bulk mode is enabled\n"); ++ ERROR_PRINTF("USB READ BURST FAILURE - bulk mode is enabled\n"); + return -1; + } else { + a = mcu_spi_write(usb_device, in_out_buf, command_size); +@@ -414,10 +416,10 @@ int lgw_usb_rb(void *com_target, uint8_t spi_mux_target, uint16_t address, uint8 + + /* determine return code */ + if (a != 0) { +- DEBUG_MSG("ERROR: USB READ BURST FAILURE\n"); ++ ERROR_PRINTF("USB READ BURST FAILURE\n"); + return -1; + } else { +- DEBUG_MSG("Note: USB read burst success\n"); ++ // DEBUG_MSG("Note: USB read burst success\n"); + memcpy(data, in_out_buf + 9, size); /* remove the first bytes, keep only the payload */ + return 0; + } +@@ -427,11 +429,11 @@ int lgw_usb_rb(void *com_target, uint8_t spi_mux_target, uint16_t address, uint8 + + int lgw_usb_set_write_mode(lgw_com_write_mode_t write_mode) { + if (write_mode >= LGW_COM_WRITE_MODE_UNKNOWN) { +- printf("ERROR: wrong write mode\n"); ++ ERROR_PRINTF("wrong write mode\n"); + return -1; + } + +- DEBUG_PRINTF("INFO: setting USB write mode to %s\n", (write_mode == LGW_COM_WRITE_MODE_SINGLE) ? "SINGLE" : "BULK"); ++ DEBUG_PRINTF("setting USB write mode to %s\n", (write_mode == LGW_COM_WRITE_MODE_SINGLE) ? "SINGLE" : "BULK"); + + _lgw_write_mode = write_mode; + +@@ -447,7 +449,7 @@ int lgw_usb_flush(void *com_target) { + /* Check input parameters */ + CHECK_NULL(com_target); + if (_lgw_write_mode != LGW_COM_WRITE_MODE_BULK) { +- printf("ERROR: %s: cannot flush in single write mode\n", __FUNCTION__); ++ ERROR_PRINTF("cannot flush in single write mode\n"); + return -1; + } + +@@ -455,7 +457,7 @@ int lgw_usb_flush(void *com_target) { + _lgw_write_mode = LGW_COM_WRITE_MODE_SINGLE; + + if (_lgw_spi_req_nb == 0) { +- printf("INFO: no SPI request to flush\n"); ++ INFO_PRINTF("no SPI request to flush\n"); + return 0; + } + +@@ -464,7 +466,7 @@ int lgw_usb_flush(void *com_target) { + DEBUG_MSG("INFO: flushing USB write buffer\n"); + a = mcu_spi_flush(usb_device); + if (a != 0) { +- printf("ERROR: Failed to flush USB write buffer\n"); ++ ERROR_PRINTF("Failed to flush USB write buffer\n"); + } + + /* reset the pending request number */ +@@ -492,10 +494,10 @@ int lgw_usb_get_temperature(void *com_target, float * temperature) { + usb_device = *(int *)com_target; + + if (mcu_get_status(usb_device, &mcu_status) != 0) { +- printf("ERROR: failed to get status from the concentrator MCU\n"); ++ ERROR_PRINTF("failed to get status from the concentrator MCU\n"); + return -1; + } +- DEBUG_PRINTF("INFO: temperature:%.1foC\n", mcu_status.temperature); ++ DEBUG_PRINTF("temperature:%.1foC\n", mcu_status.temperature); + + *temperature = mcu_status.temperature; + diff --git a/deps/lgw1302/makefile b/deps/lgw1302/makefile index 2bac66b..d019f30 100644 --- a/deps/lgw1302/makefile +++ b/deps/lgw1302/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -31,13 +31,15 @@ PLT=platform-${platform} LGWLIB=${TD}/${BD}/lib/liblgw1302.a LGWINC=${TD}/${BD}/include/lgw -LGWVERSION.default = 1.0.5 +LGWVERSION.default = 2.1.0 LGWVERSION ?= $(or ${LGWVERSION.${platform}}, ${LGWVERSION.default}) HFILES = $(wildcard ${PLT}/libloragw/inc/*.h) SRCS = $(wildcard ${PLT}/libloragw/src/*.c) ARTEFACTS = ${LGWLIB} ${LGWINC} $(patsubst %, ${LGWINC}/%, $(notdir ${HFILES}) config.h) +LGW_EXTRA_CFLAGS = -DNODEBUG # Disable DEBUG file handling +LGW_EXTRA_CFLAGS += -DSTATIONLOG # Enable station log integration all: $(if ${HFILES},${ARTEFACTS},${PLT}) ${LGWINC}: @@ -49,10 +51,10 @@ ${LGWLIB}: ${PLT}/libloragw/libloragw.a @cp $< $@ ${PLT}/libloragw/libloragw.a: ${SRCS} ${HFILES} - ${MAKE} -C ${PLT}/libloragw libloragw.a CC=${CC} AR=${AR} LD=${LD} TDfull=${TDfull} + ${MAKE} -C ${PLT}/libloragw libloragw.a CC="${CC}" AR="${AR}" LD="${LD}" TDfull="${TDfull}" EXTRA_CFLAGS="${LGW_EXTRA_CFLAGS}" ${PLT}/libloragw/inc/config.h: ${PLT}/libloragw/library.cfg - ${MAKE} -C ${PLT}/libloragw inc/config.h CC=${CC} AR=${AR} LD=${LD} TDfull=${TDfull} + ${MAKE} -C ${PLT}/libloragw inc/config.h CC="${CC}" AR="${AR}" LD="${LD}" TDfull="${TDfull}" ${LGWINC}/%.h: ${PLT}/libloragw/inc/%.h | ${LGWINC} @echo " CP ${ $@" diff --git a/deps/lgw1302/prep.sh b/deps/lgw1302/prep.sh index e2f2fe3..011ac9d 100755 --- a/deps/lgw1302/prep.sh +++ b/deps/lgw1302/prep.sh @@ -1,7 +1,7 @@ #!/bin/bash # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -29,7 +29,7 @@ set -e cd $(dirname $0) -lgwversion="V${lgwversion:-1.0.5}" +lgwversion="V${lgwversion:-2.1.0}" if [[ ! -d git-repo ]]; then git clone https://github.com/Lora-net/sx1302_hal.git git-repo diff --git a/deps/mbedtls/makefile b/deps/mbedtls/makefile index 841c352..aa12417 100644 --- a/deps/mbedtls/makefile +++ b/deps/mbedtls/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -39,8 +39,8 @@ all: $(if ${HFILES},${ARTEFACTS},${PLT}) ${MBEDINC}: @mkdir -p $@ -${PLT}/library/%.a: ${PLT} - ${MAKE} -C $< lib CC="${CC}" AR="${AR}" LD="${LD}" +${PLT}/library/%.a: ${PLT}/Makefile + ${MAKE} -C ${PLT} lib CC="${CC}" AR="${AR}" LD="${LD}" CFLAGS="-Wall -std=gnu11" ${TD}/${BD}/lib/%.a: ${PLT}/library/%.a @mkdir -p ${@D} diff --git a/deps/mbedtls/prep.sh b/deps/mbedtls/prep.sh index 4f774f0..6dcb539 100755 --- a/deps/mbedtls/prep.sh +++ b/deps/mbedtls/prep.sh @@ -1,7 +1,7 @@ #!/bin/bash # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -30,7 +30,7 @@ set -e cd $(dirname $0) if [[ ! -d git-repo ]]; then - git clone -b mbedtls-2.7.5 --single-branch --depth 1 https://github.com/ARMmbed/mbedtls.git git-repo + git clone -b mbedtls-2.28.0 --single-branch --depth 1 https://github.com/ARMmbed/mbedtls.git git-repo fi if [[ -z "$platform" ]] || [[ -z "$variant" ]]; then diff --git a/deps/smtcpico/V0.2.2-linuxpico.patch b/deps/smtcpico/V0.2.2-linuxpico.patch index 587e16c..fd4ca5a 100644 --- a/deps/smtcpico/V0.2.2-linuxpico.patch +++ b/deps/smtcpico/V0.2.2-linuxpico.patch @@ -1,3 +1,27 @@ +diff --git a/libloragw/Makefile b/libloragw/Makefile +index ea93f19..57e6864 100644 +--- a/libloragw/Makefile ++++ b/libloragw/Makefile +@@ -11,6 +11,7 @@ CC := $(CROSS_COMPILE)gcc + AR := $(CROSS_COMPILE)ar + + CFLAGS := -O2 -Wall -Wextra -std=c99 -Iinc -I. ++CFLAGS += ${EXTRA_CFLAGS} + + OBJDIR = obj + INCLUDES = $(wildcard inc/*.h) +@@ -57,9 +58,9 @@ $(OBJDIR): + + $(OBJDIR)/%.o: src/%.c $(INCLUDES) inc/config.h | $(OBJDIR) + $(CC) -c $(CFLAGS) $< -o $@ +- ++ + $(OBJDIR)/loragw_com_linux.o: src/loragw_com_linux.c $(INCLUDES) inc/config.h | $(OBJDIR) +- $(CC) -c $(CFLAGS) $< -o $@ ++ $(CC) -c $(CFLAGS) $< -o $@ + + $(OBJDIR)/loragw_com.o: src/loragw_com.c $(INCLUDES) inc/config.h | $(OBJDIR) + $(CC) -c $(CFLAGS) $< -o $@ diff --git a/libloragw/inc/loragw_fpga.h b/libloragw/inc/loragw_fpga.h new file mode 100644 index 0000000..f599f73 @@ -289,92 +313,105 @@ index 0000000..aa04060 + +#endif +/* --- EOF ------------------------------------------------------------------ */ -diff --git a/libloragw/src/loragw_hal.c b/libloragw/src/loragw_hal.c -index 2c46381..a4e4b85 100644 ---- a/libloragw/src/loragw_hal.c -+++ b/libloragw/src/loragw_hal.c -@@ -225,11 +225,18 @@ int load_firmware(uint8_t target, uint8_t *firmware, uint16_t size) { - - /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +diff --git a/libloragw/inc/loragw_stationlog.h b/libloragw/inc/loragw_stationlog.h +new file mode 100644 +index 0000000..a282b8f +--- /dev/null ++++ b/libloragw/inc/loragw_stationlog.h +@@ -0,0 +1,26 @@ ++#ifndef _LORAGW_STATIONLOG_H ++#define _LORAGW_STATIONLOG_H ++ ++#if defined(STATIONLOG) ++ ++#undef DEBUG_PRINTF ++#undef DEBUG_MSG ++ ++enum { XDEBUG=0, DEBUG, VERBOSE, INFO, NOTICE, WARNING, ERROR, CRITICAL }; ++extern void log_hal (uint8_t level, const char* fmt, ...); ++#define ERROR_PRINTF(fmt, ...) log_hal(ERROR , "[%s:%d] "fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__) ++#define INFO_PRINTF(fmt, ...) log_hal(INFO , "[%s:%d] "fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__) ++#define DEBUG_PRINTF(fmt, ...) log_hal(XDEBUG , "[%s:%d] "fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__) ++#define DEBUG_MSG(str) log_hal(XDEBUG , "[%s:%d] %s", __FUNCTION__, __LINE__, str) ++#define XDEBUG_PRINTF(fmt, ...) log_hal(XDEBUG , "[%s:%d] "fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__) ++#define XDEBUG_MSG(str) log_hal(XDEBUG , "[%s:%d] %s", __FUNCTION__, __LINE__, str) ++ ++#else // !defined(STATIONLOG) ++ ++#define ERROR_PRINTF(fmt, ...) DEBUG_PRINTF(fmt, ## __VA_ARGS__) ++#define INFO_PRINTF(fmt, ...) DEBUG_PRINTF(fmt, ## __VA_ARGS__) ++#define XDEBUG_PRINTF(fmt, ...) DEBUG_PRINTF(fmt, ## __VA_ARGS__) ++#define XDEBUG_MSG(str) DEBUG_MSG(str) ++#endif ++ ++#endif +diff --git a/libloragw/src/loragw_com_linux.c b/libloragw/src/loragw_com_linux.c +index 4ef7e37..776d63a 100644 +--- a/libloragw/src/loragw_com_linux.c ++++ b/libloragw/src/loragw_com_linux.c +@@ -52,6 +52,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + #define CHECK_NULL(a) if(a==NULL){return LGW_COM_ERROR;} + #endif -+uint8_t lgwx_device_mode = 0; -+uint8_t lgwx_beacon_len = 0; -+uint8_t lgwx_beacon_sf = 0; -+uint8_t lgwx_lbt_mode = 0; ++#include "loragw_stationlog.h" + - void lgw_constant_adjust(void) { + #define UNUSED(x) (void)(x) - /* I/Q path setup */ - // lgw_reg_w(LGW_RX_INVERT_IQ,0); /* default 0 */ - // lgw_reg_w(LGW_MODEM_INVERT_IQ,1); /* default 1 */ -+ if( lgwx_device_mode ) -+ lgw_reg_w(LGW_MODEM_INVERT_IQ,0); - // lgw_reg_w(LGW_CHIRP_INVERT_RX,1); /* default 1 */ - // lgw_reg_w(LGW_RX_EDGE_SELECT,0); /* default 0 */ - // lgw_reg_w(LGW_MBWSSF_MODEM_INVERT_IQ,0); /* default 0 */ -@@ -279,6 +286,8 @@ void lgw_constant_adjust(void) { + /* -------------------------------------------------------------------------- */ +@@ -69,7 +71,7 @@ int set_interface_attribs_linux(int fd, int speed) { - // lgw_reg_w(LGW_PREAMBLE_FINE_TIMING_GAIN,1); /* default 1 */ - // lgw_reg_w(LGW_ONLY_CRC_EN,1); /* default 1 */ -+ if( lgwx_device_mode ) -+ lgw_reg_w(LGW_ONLY_CRC_EN,0); - // lgw_reg_w(LGW_PAYLOAD_FINE_TIMING_GAIN,2); /* default 2 */ - // lgw_reg_w(LGW_TRACKING_INTEGRAL,0); /* default 0 */ - // lgw_reg_w(LGW_ADJUST_MODEM_START_OFFSET_RDX8,0); /* default 0 */ -@@ -299,11 +308,24 @@ void lgw_constant_adjust(void) { - lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_PEAK2_POS, 2); /* default 2 */ + /* Get current attributes */ + if (tcgetattr(fd, &tty) != 0) { +- DEBUG_PRINTF("ERROR: tcgetattr failed with %d - %s", errno, strerror(errno)); ++ ERROR_PRINTF("tcgetattr failed with %d - %s", errno, strerror(errno)); + return LGW_COM_ERROR; } - // lgw_reg_w(LGW_MBWSSF_ONLY_CRC_EN,1); /* default 1 */ -+ if( lgwx_device_mode ) -+ lgw_reg_w(LGW_MBWSSF_ONLY_CRC_EN,0); - // lgw_reg_w(LGW_MBWSSF_PAYLOAD_FINE_TIMING_GAIN,2); /* default 2 */ - // lgw_reg_w(LGW_MBWSSF_PREAMBLE_FINE_TIMING_GAIN,1); /* default 1 */ - // lgw_reg_w(LGW_MBWSSF_TRACKING_INTEGRAL,0); /* default 0 */ - // lgw_reg_w(LGW_MBWSSF_AGC_FREEZE_ON_DETECT,1); /* default 1 */ -+ if( lgwx_device_mode && lgwx_beacon_len ) { -+ lgw_reg_w(LGW_MBWSSF_MODEM_INVERT_IQ,0); -+ lgw_reg_w(LGW_MBWSSF_RATE_SF, lgwx_beacon_sf); -+ lgw_reg_w(LGW_MBWSSF_IMPLICIT_HEADER,1); /* no header */ -+ lgw_reg_w(LGW_MBWSSF_IMPLICIT_CRC_EN,0); -+ lgw_reg_w(LGW_MBWSSF_IMPLICIT_CODING_RATE,1); -+ lgw_reg_w(LGW_MBWSSF_IMPLICIT_PAYLOAD_LENGHT, lgwx_beacon_len); -+ } else { -+ lgw_reg_w(LGW_MBWSSF_MODEM_INVERT_IQ,1); //XXX:? correct? -+ } -+ - /* Improvement of reference clock frequency error tolerance */ - lgw_reg_w(LGW_ADJUST_MODEM_START_OFFSET_RDX4, 1); /* default 0 */ - lgw_reg_w(LGW_ADJUST_MODEM_START_OFFSET_SF12_RDX4, 4094); /* default 4092 */ -@@ -587,6 +609,11 @@ int lgw_board_setconf(struct lgw_conf_board_s conf) { - return lgw_mcu_board_setconf(conf); - } +@@ -96,7 +98,7 @@ int set_interface_attribs_linux(int fd, int speed) { -+int lgw_lbt_setconf (struct lgw_conf_lbt_s conf) { -+ (void) conf; -+ return LGW_HAL_ERROR; -+} -+ - /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + /* Set attributes */ + if (tcsetattr(fd, TCSANOW, &tty) != 0) { +- DEBUG_PRINTF("ERROR: tcsetattr failed with %d - %s", errno, strerror(errno)); ++ ERROR_PRINTF("tcsetattr failed with %d - %s", errno, strerror(errno)); + return LGW_COM_ERROR; + } - int lgw_rxrf_setconf(uint8_t rf_chain, struct lgw_conf_rxrf_s conf) { -@@ -1154,6 +1181,11 @@ int lgw_send(struct lgw_pkt_tx_s pkt_data) { - return LGW_HAL_ERROR; +@@ -113,7 +115,7 @@ int set_blocking_linux(int fd, bool blocking) { + + /* Get current attributes */ + if (tcgetattr(fd, &tty) != 0) { +- DEBUG_PRINTF("ERROR: tcgetattr failed with %d - %s", errno, strerror(errno)); ++ ERROR_PRINTF("tcgetattr failed with %d - %s", errno, strerror(errno)); + return LGW_COM_ERROR; } -+ if( lgwx_device_mode ) { -+ pkt_data.invert_pol = false; -+ pkt_data.no_crc = false; -+ } -+ - /* send packet data to concentrator MCU */ - return lgw_mcu_send(pkt_data); +@@ -122,7 +124,7 @@ int set_blocking_linux(int fd, bool blocking) { + + /* Set attributes */ + if (tcsetattr(fd, TCSANOW, &tty) != 0) { +- DEBUG_PRINTF("ERROR: tcsetattr failed with %d - %s", errno, strerror(errno)); ++ ERROR_PRINTF("tcsetattr failed with %d - %s", errno, strerror(errno)); + return LGW_COM_ERROR; + } + +@@ -184,14 +186,14 @@ int lgw_com_send_cmd_linux(lgw_com_cmd_t cmd, lgw_handle_t handle) { + /* Send command */ + lencheck = write(handle, buffertx, Tlen); + if (lencheck < 0) { +- DEBUG_PRINTF("ERROR: failed to write cmd (%d - %s)\n", errno, strerror(errno)); ++ ERROR_PRINTF("failed to write cmd (%d - %s)\n", errno, strerror(errno)); + return LGW_COM_ERROR; + } + if (lencheck != Tlen) { + DEBUG_PRINTF("WARNING: incomplete cmd written (%d)\n", (int)lencheck); + } + +- DEBUG_PRINTF("Note: sent cmd \'%c\', addr 0x%02X, length=%d\n", cmd.id, cmd.address, Clen); ++ // XDEBUG_PRINTF("Note: sent cmd \'%c\', addr 0x%02X, length=%d\n", cmd.id, cmd.address, Clen); + + return LGW_COM_SUCCESS; } -diff --git a/libloragw/src/loragw_com_linux.c b/libloragw/src/loragw_com_linux.c -index 4ef7e37..d708321 100644 ---- a/libloragw/src/loragw_com_linux.c -+++ b/libloragw/src/loragw_com_linux.c -@@ -205,6 +205,7 @@ int lgw_com_receive_ans_linux(lgw_com_ans_t *ans, lgw_handle_t handle) { +@@ -205,6 +207,7 @@ int lgw_com_receive_ans_linux(lgw_com_ans_t *ans, lgw_handle_t handle) { size_t cmd_size; ssize_t buf_size = 0; ssize_t lencheck; @@ -382,7 +419,7 @@ index 4ef7e37..d708321 100644 /* Initialize variables */ memset(bufferrx, 0, sizeof bufferrx); -@@ -213,8 +214,17 @@ int lgw_com_receive_ans_linux(lgw_com_ans_t *ans, lgw_handle_t handle) { +@@ -213,8 +216,17 @@ int lgw_com_receive_ans_linux(lgw_com_ans_t *ans, lgw_handle_t handle) { buffer_idx = 0; while ((checkcmd_linux(bufferrx[0]) != true) || (buffer_idx < CMD_HEADER_RX_SIZE)) { lencheck = read(handle, &bufferrx[buffer_idx], CMD_HEADER_RX_SIZE - buffer_idx); @@ -391,18 +428,54 @@ index 4ef7e37..d708321 100644 + if (lencheck==0) { + // In case of non-blocking IO we may get 0 bytes back + if( ++readtries > 4 ) { -+ printf("ERROR: failed to read from communication bridge - no data\n"); ++ ERROR_PRINTF("failed to read from communication bridge - no data\n"); + return LGW_COM_ERROR; + } + wait_ns_linux(250000); + } + else if (lencheck < 0) { + //DEBUG_PRINTF("WARNING: failed to read from communication bridge (%d - %s), retry...\n", errno, strerror(errno)); -+ printf("ERROR: failed to read from communication bridge (%d - %s), retry...\n", errno, strerror(errno)); ++ ERROR_PRINTF("failed to read from communication bridge (%d - %s), retry...\n", errno, strerror(errno)); return LGW_COM_ERROR; } buffer_idx += lencheck; -@@ -266,9 +276,7 @@ int lgw_com_receive_ans_linux(lgw_com_ans_t *ans, lgw_handle_t handle) { +@@ -222,7 +234,7 @@ int lgw_com_receive_ans_linux(lgw_com_ans_t *ans, lgw_handle_t handle) { + + cmd_size = (bufferrx[1] << 8) + bufferrx[2]; + +- DEBUG_PRINTF("Note: received answer header for cmd \'%c\', length=%zd, ack=%u\n", bufferrx[0], cmd_size, bufferrx[3]); ++ // XDEBUG_PRINTF("Note: received answer header for cmd \'%c\', length=%zd, ack=%u\n", bufferrx[0], cmd_size, bufferrx[3]); + + /* Read answer Data */ + if (cmd_size > 0) { +@@ -233,7 +245,7 @@ int lgw_com_receive_ans_linux(lgw_com_ans_t *ans, lgw_handle_t handle) { + } + /* Check that data size does not exceed buffer size */ + if (cmd_size > CMD_DATA_RX_SIZE) { +- DEBUG_PRINTF("ERROR: exceed read buffer size, abort. (%zd)\n", cmd_size); ++ ERROR_PRINTF("exceed read buffer size, abort. (%zd)\n", cmd_size); + return LGW_COM_ERROR; + } + /* Read the answer */ +@@ -241,7 +253,7 @@ int lgw_com_receive_ans_linux(lgw_com_ans_t *ans, lgw_handle_t handle) { + while (buffer_idx < cmd_size) { + lencheck = read(handle, &bufferrx[CMD_HEADER_RX_SIZE + buffer_idx], cmd_size - buffer_idx); + if (lencheck < 0) { +- DEBUG_PRINTF("ERROR: failed to read cmd answer (%d - %s)\n", errno, strerror(errno)); ++ ERROR_PRINTF("failed to read cmd answer (%d - %s)\n", errno, strerror(errno)); + return LGW_COM_ERROR; + } + buffer_idx += lencheck; +@@ -255,7 +267,7 @@ int lgw_com_receive_ans_linux(lgw_com_ans_t *ans, lgw_handle_t handle) { + ans->ans_data[i] = bufferrx[CMD_HEADER_RX_SIZE + i]; + } + +- DEBUG_PRINTF("Note: received answer for cmd \'%c\', length=%zd\n", bufferrx[0], cmd_size); ++ // XDEBUG_PRINTF("Note: received answer for cmd \'%c\', length=%zd\n", bufferrx[0], cmd_size); + + return LGW_COM_SUCCESS; + } +@@ -266,40 +278,48 @@ int lgw_com_receive_ans_linux(lgw_com_ans_t *ans, lgw_handle_t handle) { int lgw_com_open_linux(void **com_target_ptr, const char *com_path) { int *usb_device = NULL; @@ -413,7 +486,12 @@ index 4ef7e37..d708321 100644 /*check input variables*/ CHECK_NULL(com_target_ptr); -@@ -280,26 +288,36 @@ int lgw_com_open_linux(void **com_target_ptr, const char *com_path) { + + usb_device = malloc(sizeof(int)); + if (usb_device == NULL) { +- DEBUG_MSG("ERROR : MALLOC FAIL\n"); ++ ERROR_PRINTF("MALLOC FAIL\n"); + return LGW_COM_ERROR; } /* open tty port */ @@ -422,7 +500,7 @@ index 4ef7e37..d708321 100644 + fd = open(com_path, O_RDWR | O_NOCTTY | O_SYNC); if (fd < 0) { - printf("ERROR: failed to open COM port %s - %s\n", portname, strerror(errno)); -+ printf("ERROR: failed to open COM port %s - %s\n", com_path, strerror(errno)); ++ ERROR_PRINTF("failed to open COM port %s - %s\n", com_path, strerror(errno)); } else { - x = set_interface_attribs_linux(fd, B115200); - x |= set_blocking_linux(fd, true); @@ -432,7 +510,7 @@ index 4ef7e37..d708321 100644 - return LGW_COM_ERROR; + if( set_interface_attribs_linux(fd, B115200) != LGW_COM_SUCCESS || + set_blocking_linux(fd, false) != LGW_COM_SUCCESS ) { -+ printf("ERROR: failed to configure COM port %s\n", com_path); ++ ERROR_PRINTF("failed to configure COM port %s\n", com_path); + goto fail; } @@ -446,7 +524,7 @@ index 4ef7e37..d708321 100644 + int err = lgw_mcu_get_unique_id(eui); // NOTE: uses *com_target_ptr! + if( err == LGW_MCU_SUCCESS ) { + if( set_blocking_linux(fd, true) != LGW_COM_SUCCESS ) { -+ printf("ERROR: failed to configure COM port %s\n", com_path); ++ ERROR_PRINTF("failed to configure COM port %s\n", com_path); + goto fail; + } + return LGW_COM_SUCCESS; @@ -461,3 +539,998 @@ index 4ef7e37..d708321 100644 return LGW_COM_ERROR; } +@@ -319,7 +339,7 @@ int lgw_com_close_linux(void *com_target) { + + /* determine return code */ + if (a < 0) { +- printf("ERROR: failed to close COM port - %s\n", strerror(errno)); ++ ERROR_PRINTF("failed to close COM port - %s\n", strerror(errno)); + return LGW_COM_ERROR; + } else { + DEBUG_MSG("Note : USB port closed\n"); +diff --git a/libloragw/src/loragw_hal.c b/libloragw/src/loragw_hal.c +index 2c46381..270201b 100644 +--- a/libloragw/src/loragw_hal.c ++++ b/libloragw/src/loragw_hal.c +@@ -45,6 +45,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + #define CHECK_NULL(a) if(a==NULL){return LGW_HAL_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + #define IF_HZ_TO_REG(f) (f << 5)/15625 + #define SET_PPM_ON(bw,dr) (((bw == BW_125KHZ) && ((dr == DR_LORA_SF11) || (dr == DR_LORA_SF12))) || ((bw == BW_250KHZ) && (dr == DR_LORA_SF12))) + #define TRACE() fprintf(stderr, "@ %s %d\n", __FUNCTION__, __LINE__); +@@ -182,20 +184,20 @@ int load_firmware(uint8_t target, uint8_t *firmware, uint16_t size) { + CHECK_NULL(firmware); + if (target == MCU_ARB) { + if (size != MCU_ARB_FW_BYTE) { +- DEBUG_MSG("ERROR: NOT A VALID SIZE FOR MCU ARG FIRMWARE\n"); ++ ERROR_PRINTF("NOT A VALID SIZE FOR MCU ARG FIRMWARE\n"); + return -1; + } + reg_rst = LGW_MCU_RST_0; + reg_sel = LGW_MCU_SELECT_MUX_0; + } else if (target == MCU_AGC) { + if (size != MCU_AGC_FW_BYTE) { +- DEBUG_MSG("ERROR: NOT A VALID SIZE FOR MCU AGC FIRMWARE\n"); ++ ERROR_PRINTF("NOT A VALID SIZE FOR MCU AGC FIRMWARE\n"); + return -1; + } + reg_rst = LGW_MCU_RST_1; + reg_sel = LGW_MCU_SELECT_MUX_1; + } else { +- DEBUG_MSG("ERROR: NOT A VALID TARGET FOR LOADING FIRMWARE\n"); ++ ERROR_PRINTF("NOT A VALID TARGET FOR LOADING FIRMWARE\n"); + return -1; + } + +@@ -225,11 +227,18 @@ int load_firmware(uint8_t target, uint8_t *firmware, uint16_t size) { + + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + ++uint8_t lgwx_device_mode = 0; ++uint8_t lgwx_beacon_len = 0; ++uint8_t lgwx_beacon_sf = 0; ++uint8_t lgwx_lbt_mode = 0; ++ + void lgw_constant_adjust(void) { + + /* I/Q path setup */ + // lgw_reg_w(LGW_RX_INVERT_IQ,0); /* default 0 */ + // lgw_reg_w(LGW_MODEM_INVERT_IQ,1); /* default 1 */ ++ if( lgwx_device_mode ) ++ lgw_reg_w(LGW_MODEM_INVERT_IQ,0); + // lgw_reg_w(LGW_CHIRP_INVERT_RX,1); /* default 1 */ + // lgw_reg_w(LGW_RX_EDGE_SELECT,0); /* default 0 */ + // lgw_reg_w(LGW_MBWSSF_MODEM_INVERT_IQ,0); /* default 0 */ +@@ -279,6 +288,8 @@ void lgw_constant_adjust(void) { + + // lgw_reg_w(LGW_PREAMBLE_FINE_TIMING_GAIN,1); /* default 1 */ + // lgw_reg_w(LGW_ONLY_CRC_EN,1); /* default 1 */ ++ if( lgwx_device_mode ) ++ lgw_reg_w(LGW_ONLY_CRC_EN,0); + // lgw_reg_w(LGW_PAYLOAD_FINE_TIMING_GAIN,2); /* default 2 */ + // lgw_reg_w(LGW_TRACKING_INTEGRAL,0); /* default 0 */ + // lgw_reg_w(LGW_ADJUST_MODEM_START_OFFSET_RDX8,0); /* default 0 */ +@@ -299,11 +310,24 @@ void lgw_constant_adjust(void) { + lgw_reg_w(LGW_MBWSSF_FRAME_SYNCH_PEAK2_POS, 2); /* default 2 */ + } + // lgw_reg_w(LGW_MBWSSF_ONLY_CRC_EN,1); /* default 1 */ ++ if( lgwx_device_mode ) ++ lgw_reg_w(LGW_MBWSSF_ONLY_CRC_EN,0); + // lgw_reg_w(LGW_MBWSSF_PAYLOAD_FINE_TIMING_GAIN,2); /* default 2 */ + // lgw_reg_w(LGW_MBWSSF_PREAMBLE_FINE_TIMING_GAIN,1); /* default 1 */ + // lgw_reg_w(LGW_MBWSSF_TRACKING_INTEGRAL,0); /* default 0 */ + // lgw_reg_w(LGW_MBWSSF_AGC_FREEZE_ON_DETECT,1); /* default 1 */ + ++ if( lgwx_device_mode && lgwx_beacon_len ) { ++ lgw_reg_w(LGW_MBWSSF_MODEM_INVERT_IQ,0); ++ lgw_reg_w(LGW_MBWSSF_RATE_SF, lgwx_beacon_sf); ++ lgw_reg_w(LGW_MBWSSF_IMPLICIT_HEADER,1); /* no header */ ++ lgw_reg_w(LGW_MBWSSF_IMPLICIT_CRC_EN,0); ++ lgw_reg_w(LGW_MBWSSF_IMPLICIT_CODING_RATE,1); ++ lgw_reg_w(LGW_MBWSSF_IMPLICIT_PAYLOAD_LENGHT, lgwx_beacon_len); ++ } else { ++ lgw_reg_w(LGW_MBWSSF_MODEM_INVERT_IQ,1); //XXX:? correct? ++ } ++ + /* Improvement of reference clock frequency error tolerance */ + lgw_reg_w(LGW_ADJUST_MODEM_START_OFFSET_RDX4, 1); /* default 0 */ + lgw_reg_w(LGW_ADJUST_MODEM_START_OFFSET_SF12_RDX4, 4094); /* default 4092 */ +@@ -405,15 +429,15 @@ int lgw_calibrate_sx125x(uint8_t *cal_fw, uint8_t idx_start, uint8_t idx_nb) { + + /* check parameters */ + if (cal_fw == NULL) { +- DEBUG_MSG("ERROR: invalid parameter, null pointer\n"); ++ ERROR_PRINTF("invalid parameter, null pointer\n"); + return LGW_HAL_ERROR; + } + if ((idx_start < 5) || (idx_start > 15)) { +- DEBUG_MSG("ERROR: invalid parameter, calibration offset index start must be [5-15]\n"); ++ ERROR_PRINTF("invalid parameter, calibration offset index start must be [5-15]\n"); + return LGW_HAL_ERROR; + } + if (idx_nb > 8) { +- DEBUG_MSG("ERROR: invalid parameter, calibration offset index number must be <= 8\n"); ++ ERROR_PRINTF("invalid parameter, calibration offset index number must be <= 8\n"); + return LGW_HAL_ERROR; + } + +@@ -437,12 +461,12 @@ int lgw_calibrate_sx125x(uint8_t *cal_fw, uint8_t idx_start, uint8_t idx_nb) { + /* setup the radios */ + err = lgw_setup_sx125x(0, rf_clkout, rf_enable[0], rf_radio_type[0], rf_rx_freq[0]); + if (err != 0) { +- DEBUG_MSG("ERROR: Failed to setup sx125x radio for RF chain 0\n"); ++ ERROR_PRINTF("Failed to setup sx125x radio for RF chain 0\n"); + return LGW_HAL_ERROR; + } + err = lgw_setup_sx125x(1, rf_clkout, rf_enable[1], rf_radio_type[1], rf_rx_freq[1]); + if (err != 0) { +- DEBUG_MSG("ERROR: Failed to setup sx125x radio for RF chain 0\n"); ++ ERROR_PRINTF("Failed to setup sx125x radio for RF chain 0\n"); + return LGW_HAL_ERROR; + } + +@@ -474,7 +498,7 @@ int lgw_calibrate_sx125x(uint8_t *cal_fw, uint8_t idx_start, uint8_t idx_nb) { + cal_cmd |= 0x00; /* Bit 5: 0: SX1257, 1: SX1255 */ + break; + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type[0]); ++ ERROR_PRINTF("UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type[0]); + break; + } + +@@ -518,17 +542,17 @@ int lgw_calibrate_sx125x(uint8_t *cal_fw, uint8_t idx_start, uint8_t idx_nb) { + bit 6: radio B TX DC Offset correction successful + */ + if ((cal_status & 0x81) != 0x81) { +- DEBUG_PRINTF("ERROR: CALIBRATION FAILURE (STATUS = 0x%X)\n", cal_status); ++ ERROR_PRINTF("CALIBRATION FAILURE (STATUS = 0x%X)\n", cal_status); + return LGW_HAL_ERROR; + } else { + DEBUG_PRINTF("Note: calibration finished (status = 0x%X)\n", cal_status); + } + if (rf_enable[0] && ((cal_status & 0x02) == 0)) { +- DEBUG_MSG("ERROR: calibration could not access radio A\n"); ++ ERROR_PRINTF("calibration could not access radio A\n"); + return LGW_HAL_ERROR; + } + if (rf_enable[1] && ((cal_status & 0x04) == 0)) { +- DEBUG_MSG("ERROR: calibration could not access radio B\n"); ++ ERROR_PRINTF("calibration could not access radio B\n"); + return LGW_HAL_ERROR; + } + if (rf_enable[0] && ((cal_status & 0x08) == 0)) { +@@ -573,7 +597,7 @@ int lgw_calibrate_sx125x(uint8_t *cal_fw, uint8_t idx_start, uint8_t idx_nb) { + int lgw_board_setconf(struct lgw_conf_board_s conf) { + /* check if the concentrator is running */ + if (lgw_is_started == true) { +- DEBUG_MSG("ERROR: CONCENTRATOR IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); ++ ERROR_PRINTF("CONCENTRATOR IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); + return LGW_HAL_ERROR; + } + +@@ -587,24 +611,29 @@ int lgw_board_setconf(struct lgw_conf_board_s conf) { + return lgw_mcu_board_setconf(conf); + } + ++int lgw_lbt_setconf (struct lgw_conf_lbt_s conf) { ++ (void) conf; ++ return LGW_HAL_ERROR; ++} ++ + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + + int lgw_rxrf_setconf(uint8_t rf_chain, struct lgw_conf_rxrf_s conf) { + /* check if the concentrator is running */ + if (lgw_is_started == true) { +- DEBUG_MSG("ERROR: CONCENTRATOR IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); ++ ERROR_PRINTF("CONCENTRATOR IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); + return LGW_HAL_ERROR; + } + + /* check input range (segfault prevention) */ + if (rf_chain >= LGW_RF_CHAIN_NB) { +- DEBUG_MSG("ERROR: NOT A VALID RF_CHAIN NUMBER\n"); ++ ERROR_PRINTF("NOT A VALID RF_CHAIN NUMBER\n"); + return LGW_HAL_ERROR; + } + + /* check if radio type is supported */ + if ((conf.type != LGW_RADIO_TYPE_SX1255) && (conf.type != LGW_RADIO_TYPE_SX1257)) { +- DEBUG_MSG("ERROR: NOT A VALID RADIO TYPE\n"); ++ ERROR_PRINTF("NOT A VALID RADIO TYPE\n"); + return LGW_HAL_ERROR; + } + +@@ -629,13 +658,13 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + + /* check if the concentrator is running */ + if (lgw_is_started == true) { +- DEBUG_MSG("ERROR: CONCENTRATOR IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); ++ ERROR_PRINTF("CONCENTRATOR IS RUNNING, STOP IT BEFORE TOUCHING CONFIGURATION\n"); + return LGW_HAL_ERROR; + } + + /* check input range (segfault prevention) */ + if (if_chain >= LGW_IF_CHAIN_NB) { +- DEBUG_PRINTF("ERROR: %d NOT A VALID IF_CHAIN NUMBER\n", if_chain); ++ ERROR_PRINTF("%d NOT A VALID IF_CHAIN NUMBER\n", if_chain); + return LGW_HAL_ERROR; + } + +@@ -649,10 +678,10 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + + /* check 'general' parameters */ + if (ifmod_config[if_chain] == IF_UNDEFINED) { +- DEBUG_PRINTF("ERROR: IF CHAIN %d NOT CONFIGURABLE\n", if_chain); ++ ERROR_PRINTF("IF CHAIN %d NOT CONFIGURABLE\n", if_chain); + } + if (conf.rf_chain >= LGW_RF_CHAIN_NB) { +- DEBUG_MSG("ERROR: INVALID RF_CHAIN TO ASSOCIATE WITH A LORA_STD IF CHAIN\n"); ++ ERROR_PRINTF("INVALID RF_CHAIN TO ASSOCIATE WITH A LORA_STD IF CHAIN\n"); + return LGW_HAL_ERROR; + } + switch (conf.bandwidth) { +@@ -669,10 +698,10 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + + bw_hz = lgw_bw_getval(conf.bandwidth); + if ((conf.freq_hz + ((bw_hz == -1) ? LGW_REF_BW : bw_hz) / 2) > ((int32_t)rf_rx_bandwidth / 2)) { +- DEBUG_PRINTF("ERROR: IF FREQUENCY %d TOO HIGH\n", conf.freq_hz); ++ ERROR_PRINTF("IF FREQUENCY %d TOO HIGH\n", conf.freq_hz); + return LGW_HAL_ERROR; + } else if ((conf.freq_hz - ((bw_hz == -1) ? LGW_REF_BW : bw_hz) / 2) < -((int32_t)rf_rx_bandwidth / 2)) { +- DEBUG_PRINTF("ERROR: IF FREQUENCY %d TOO LOW\n", conf.freq_hz); ++ ERROR_PRINTF("IF FREQUENCY %d TOO LOW\n", conf.freq_hz); + return LGW_HAL_ERROR; + } + +@@ -689,11 +718,11 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + } + /* check BW & DR */ + if (!IS_LORA_BW(conf.bandwidth)) { +- DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA_STD IF CHAIN\n"); ++ ERROR_PRINTF("BANDWIDTH NOT SUPPORTED BY LORA_STD IF CHAIN\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_STD_DR(conf.datarate)) { +- DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY LORA_STD IF CHAIN\n"); ++ ERROR_PRINTF("DATARATE NOT SUPPORTED BY LORA_STD IF CHAIN\n"); + return LGW_HAL_ERROR; + } + /* set internal configuration */ +@@ -721,11 +750,11 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + } + /* check BW & DR */ + if (conf.bandwidth != BW_125KHZ) { +- DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); ++ ERROR_PRINTF("BANDWIDTH NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_MULTI_DR(conf.datarate)) { +- DEBUG_MSG("ERROR: DATARATE(S) NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); ++ ERROR_PRINTF("DATARATE(S) NOT SUPPORTED BY LORA_MULTI IF CHAIN\n"); + return LGW_HAL_ERROR; + } + /* set internal configuration */ +@@ -747,11 +776,11 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + } + /* check BW & DR */ + if(!IS_FSK_BW(conf.bandwidth)) { +- DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY FSK IF CHAIN\n"); ++ ERROR_PRINTF("BANDWIDTH NOT SUPPORTED BY FSK IF CHAIN\n"); + return LGW_HAL_ERROR; + } + if(!IS_FSK_DR(conf.datarate)) { +- DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); ++ ERROR_PRINTF("DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); + return LGW_HAL_ERROR; + } + /* set internal configuration */ +@@ -768,7 +797,7 @@ int lgw_rxif_setconf(uint8_t if_chain, struct lgw_conf_rxif_s conf) { + break; + + default: +- DEBUG_PRINTF("ERROR: IF CHAIN %d TYPE NOT SUPPORTED\n", if_chain); ++ ERROR_PRINTF("IF CHAIN %d TYPE NOT SUPPORTED\n", if_chain); + return LGW_HAL_ERROR; + } + +@@ -783,7 +812,7 @@ int lgw_txgain_setconf(struct lgw_tx_gain_lut_s *conf) { + + /* Check LUT size */ + if ((conf->size < 1) || (conf->size > TX_GAIN_LUT_SIZE_MAX)) { +- DEBUG_PRINTF("ERROR: TX gain LUT must have at least one entry and maximum %d entries\n", TX_GAIN_LUT_SIZE_MAX); ++ ERROR_PRINTF("TX gain LUT must have at least one entry and maximum %d entries\n", TX_GAIN_LUT_SIZE_MAX); + return LGW_HAL_ERROR; + } + +@@ -792,19 +821,19 @@ int lgw_txgain_setconf(struct lgw_tx_gain_lut_s *conf) { + for (i = 0; i < txgain_lut.size; i++) { + /* Check gain range */ + if (conf->lut[i].dig_gain > 3) { +- DEBUG_MSG("ERROR: TX gain LUT: SX1301 digital gain must be between 0 and 3\n"); ++ ERROR_PRINTF("TX gain LUT: SX1301 digital gain must be between 0 and 3\n"); + return LGW_HAL_ERROR; + } + if (conf->lut[i].dac_gain != 3) { +- DEBUG_MSG("ERROR: TX gain LUT: SX1257 DAC gains != 3 are not supported\n"); ++ ERROR_PRINTF("TX gain LUT: SX1257 DAC gains != 3 are not supported\n"); + return LGW_HAL_ERROR; + } + if (conf->lut[i].mix_gain > 15) { +- DEBUG_MSG("ERROR: TX gain LUT: SX1257 mixer gain must not exceed 15\n"); ++ ERROR_PRINTF("TX gain LUT: SX1257 mixer gain must not exceed 15\n"); + return LGW_HAL_ERROR; + } + if (conf->lut[i].pa_gain > 3) { +- DEBUG_MSG("ERROR: TX gain LUT: External PA gain must not exceed 3\n"); ++ ERROR_PRINTF("TX gain LUT: External PA gain must not exceed 3\n"); + return LGW_HAL_ERROR; + } + +@@ -838,13 +867,13 @@ int lgw_start(void) { + /* Calibrate radios */ + err = lgw_calibrate_sx125x(callow_firmware, 5, 8); + if (err != LGW_HAL_SUCCESS) { +- DEBUG_MSG("ERROR: Failed to calibrate sx125x radios (5-12)\n"); ++ ERROR_PRINTF("Failed to calibrate sx125x radios (5-12)\n"); + return LGW_HAL_ERROR; + } + wait_ms(5); + err = lgw_calibrate_sx125x(cal_firmware, 8, 8); + if (err != LGW_HAL_SUCCESS) { +- DEBUG_MSG("ERROR: Failed to calibrate sx125x radios (8-15)\n"); ++ ERROR_PRINTF("Failed to calibrate sx125x radios (8-15)\n"); + return LGW_HAL_ERROR; + } + +@@ -857,7 +886,7 @@ int lgw_start(void) { + + /* Sanity check for RX frequency */ + if (rf_rx_freq[0] == 0) { +- DEBUG_MSG("ERROR: wrong configuration, rf_rx_freq[0] is not set\n"); ++ ERROR_PRINTF("wrong configuration, rf_rx_freq[0] is not set\n"); + return LGW_HAL_ERROR; + } + +@@ -919,7 +948,7 @@ int lgw_start(void) { + lgw_reg_w(LGW_MBWSSF_MODEM_BW, 2); + break; + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", lora_rx_bw); ++ ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", lora_rx_bw); + return LGW_HAL_ERROR; + } + switch(lora_rx_sf) { +@@ -942,7 +971,7 @@ int lgw_start(void) { + lgw_reg_w(LGW_MBWSSF_RATE_SF, 12); + break; + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", lora_rx_sf); ++ ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", lora_rx_sf); + return LGW_HAL_ERROR; + } + lgw_reg_w(LGW_MBWSSF_PPM_OFFSET, lora_rx_ppm_offset); /* default 0 */ +@@ -986,14 +1015,14 @@ int lgw_start(void) { + lgw_reg_r(LGW_DBG_AGC_MCU_RAM_DATA, &read_val); + fw_version = (uint8_t)read_val; + if (fw_version != FW_VERSION_AGC) { +- DEBUG_PRINTF("ERROR: Version of AGC firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_AGC); ++ ERROR_PRINTF("Version of AGC firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_AGC); + return LGW_HAL_ERROR; + } + lgw_reg_w(LGW_DBG_ARB_MCU_RAM_ADDR, FW_VERSION_ADDR); + lgw_reg_r(LGW_DBG_ARB_MCU_RAM_DATA, &read_val); + fw_version = (uint8_t)read_val; + if (fw_version != FW_VERSION_ARB) { +- DEBUG_PRINTF("ERROR: Version of arbiter firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_ARB); ++ ERROR_PRINTF("Version of arbiter firmware not expected, actual:%d expected:%d\n", fw_version, FW_VERSION_ARB); + return LGW_HAL_ERROR; + } + +@@ -1002,7 +1031,7 @@ int lgw_start(void) { + + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != 0x10) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + +@@ -1015,7 +1044,7 @@ int lgw_start(void) { + wait_ms(1); + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != (0x30 + i)) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + } +@@ -1028,7 +1057,7 @@ int lgw_start(void) { + wait_ms(10); + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != 0x30) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + } +@@ -1040,7 +1069,7 @@ int lgw_start(void) { + wait_ms(10); + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != 0x33) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + +@@ -1051,7 +1080,7 @@ int lgw_start(void) { + wait_ms(10); + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != 0x30) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + +@@ -1063,7 +1092,7 @@ int lgw_start(void) { + DEBUG_MSG("Info: putting back original RADIO_SELECT value\n"); + lgw_reg_r(LGW_MCU_AGC_STATUS, &read_val); + if (read_val != 0x40) { +- DEBUG_PRINTF("ERROR: AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); ++ ERROR_PRINTF("AGC FIRMWARE INITIALIZATION FAILURE, STATUS 0x%02X\n", (uint8_t)read_val); + return LGW_HAL_ERROR; + } + +@@ -1089,7 +1118,7 @@ int lgw_stop(void) { + int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { + /* check input variables */ + if ((max_pkt == 0) || (max_pkt > LGW_PKT_FIFO_SIZE)) { +- DEBUG_PRINTF("ERROR: %d = INVALID MAX NUMBER OF PACKETS TO FETCH\n", max_pkt); ++ ERROR_PRINTF("%d = INVALID MAX NUMBER OF PACKETS TO FETCH\n", max_pkt); + return LGW_HAL_ERROR; + } + +@@ -1102,58 +1131,63 @@ int lgw_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { + int lgw_send(struct lgw_pkt_tx_s pkt_data) { + /* check input range (segfault prevention) */ + if (pkt_data.rf_chain >= LGW_RF_CHAIN_NB) { +- DEBUG_MSG("ERROR: INVALID RF_CHAIN TO SEND PACKETS\n"); ++ ERROR_PRINTF("INVALID RF_CHAIN TO SEND PACKETS\n"); + return LGW_HAL_ERROR; + } + + /* check input variables */ + if (rf_tx_enable[pkt_data.rf_chain] == false) { +- DEBUG_MSG("ERROR: SELECTED RF_CHAIN IS DISABLED FOR TX ON SELECTED BOARD\n"); ++ ERROR_PRINTF("SELECTED RF_CHAIN IS DISABLED FOR TX ON SELECTED BOARD\n"); + return LGW_HAL_ERROR; + } + if (rf_enable[pkt_data.rf_chain] == false) { +- DEBUG_MSG("ERROR: SELECTED RF_CHAIN IS DISABLED\n"); ++ ERROR_PRINTF("SELECTED RF_CHAIN IS DISABLED\n"); + return LGW_HAL_ERROR; + } + if (!IS_TX_MODE(pkt_data.tx_mode)) { +- DEBUG_MSG("ERROR: TX_MODE NOT SUPPORTED\n"); ++ ERROR_PRINTF("TX_MODE NOT SUPPORTED\n"); + return LGW_HAL_ERROR; + } + if (pkt_data.modulation == MOD_LORA) { + if (!IS_LORA_BW(pkt_data.bandwidth)) { +- DEBUG_MSG("ERROR: BANDWIDTH NOT SUPPORTED BY LORA TX\n"); ++ ERROR_PRINTF("BANDWIDTH NOT SUPPORTED BY LORA TX\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_STD_DR(pkt_data.datarate)) { +- DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY LORA TX\n"); ++ ERROR_PRINTF("DATARATE NOT SUPPORTED BY LORA TX\n"); + return LGW_HAL_ERROR; + } + if (!IS_LORA_CR(pkt_data.coderate)) { +- DEBUG_MSG("ERROR: CODERATE NOT SUPPORTED BY LORA TX\n"); ++ ERROR_PRINTF("CODERATE NOT SUPPORTED BY LORA TX\n"); + return LGW_HAL_ERROR; + } + if (pkt_data.size > 255) { +- DEBUG_MSG("ERROR: PAYLOAD LENGTH TOO BIG FOR LORA TX\n"); ++ ERROR_PRINTF("PAYLOAD LENGTH TOO BIG FOR LORA TX\n"); + return LGW_HAL_ERROR; + } + } else if (pkt_data.modulation == MOD_FSK) { + if ((pkt_data.f_dev < 1) || (pkt_data.f_dev > 200)) { +- DEBUG_MSG("ERROR: TX FREQUENCY DEVIATION OUT OF ACCEPTABLE RANGE\n"); ++ ERROR_PRINTF("TX FREQUENCY DEVIATION OUT OF ACCEPTABLE RANGE\n"); + return LGW_HAL_ERROR; + } + if (!IS_FSK_DR(pkt_data.datarate)) { +- DEBUG_MSG("ERROR: DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); ++ ERROR_PRINTF("DATARATE NOT SUPPORTED BY FSK IF CHAIN\n"); + return LGW_HAL_ERROR; + } + if (pkt_data.size > 255) { +- DEBUG_MSG("ERROR: PAYLOAD LENGTH TOO BIG FOR FSK TX\n"); ++ ERROR_PRINTF("PAYLOAD LENGTH TOO BIG FOR FSK TX\n"); + return LGW_HAL_ERROR; + } + } else { +- DEBUG_MSG("ERROR: INVALID TX MODULATION\n"); ++ ERROR_PRINTF("INVALID TX MODULATION\n"); + return LGW_HAL_ERROR; + } + ++ if( lgwx_device_mode ) { ++ pkt_data.invert_pol = false; ++ pkt_data.no_crc = false; ++ } ++ + /* send packet data to concentrator MCU */ + return lgw_mcu_send(pkt_data); + } +@@ -1184,7 +1218,7 @@ int lgw_status(uint8_t select, uint8_t *code) { + return LGW_HAL_SUCCESS; + + } else { +- DEBUG_MSG("ERROR: SELECTION INVALID, NO STATUS TO RETURN\n"); ++ ERROR_PRINTF("SELECTION INVALID, NO STATUS TO RETURN\n"); + return LGW_HAL_ERROR; + } + } +@@ -1233,7 +1267,7 @@ uint32_t lgw_time_on_air(struct lgw_pkt_tx_s *packet) { + if (val != -1) { + BW = (uint16_t)(val / 1E3); + } else { +- DEBUG_PRINTF("ERROR: Cannot compute time on air for this packet, unsupported bandwidth (0x%02X)\n", packet->bandwidth); ++ ERROR_PRINTF("Cannot compute time on air for this packet, unsupported bandwidth (0x%02X)\n", packet->bandwidth); + return 0; + } + +@@ -1242,7 +1276,7 @@ uint32_t lgw_time_on_air(struct lgw_pkt_tx_s *packet) { + if (val != -1) { + SF = (uint8_t)val; + } else { +- DEBUG_PRINTF("ERROR: Cannot compute time on air for this packet, unsupported datarate (0x%02X)\n", packet->datarate); ++ ERROR_PRINTF("Cannot compute time on air for this packet, unsupported datarate (0x%02X)\n", packet->datarate); + return 0; + } + +diff --git a/libloragw/src/loragw_mcu.c b/libloragw/src/loragw_mcu.c +index 9bfe510..960dbec 100644 +--- a/libloragw/src/loragw_mcu.c ++++ b/libloragw/src/loragw_mcu.c +@@ -46,6 +46,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + #define CHECK_NULL(a) if(a==NULL){return LGW_COM_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE SHARED VARIABLES (GLOBAL) ------------------------------------ */ + +@@ -84,13 +86,13 @@ int lgw_mcu_board_setconf(struct lgw_conf_board_s conf) { + /* send command to MCU */ + x = lgw_com_send_command(lgw_com_target, cmd, &ans); + if (x != LGW_COM_SUCCESS) { +- printf("ERROR: failed to configure board\n"); ++ ERROR_PRINTF("failed to configure board\n"); + return LGW_MCU_ERROR; + } + + /* check command acknoledge */ + if (ans.status != ACK_OK) { +- printf("ERROR: failed to configure board, ACK failed\n"); ++ ERROR_PRINTF("failed to configure board, ACK failed\n"); + return LGW_MCU_ERROR; + } + +@@ -145,13 +147,13 @@ int lgw_mcu_rxrf_setconf(uint8_t rfchain, struct lgw_conf_rxrf_s conf) { + /* send command to MCU */ + x = lgw_com_send_command(lgw_com_target, cmd, &ans); + if (x != LGW_COM_SUCCESS) { +- printf("ERROR: failed to send rxrf configuration\n"); ++ ERROR_PRINTF("failed to send rxrf configuration\n"); + return LGW_MCU_ERROR; + } + + /* check command acknoledge */ + if (ans.status != ACK_OK) { +- printf("ERROR: rxrf configuration, ACK failed\n"); ++ ERROR_PRINTF("rxrf configuration, ACK failed\n"); + return LGW_MCU_ERROR; + } + +@@ -219,13 +221,13 @@ int lgw_mcu_rxif_setconf(uint8_t ifchain, struct lgw_conf_rxif_s conf) { + /* send command to MCU */ + x = lgw_com_send_command(lgw_com_target, cmd, &ans); + if (x != LGW_COM_SUCCESS) { +- printf("ERROR: failed to send rxif configuration\n"); ++ ERROR_PRINTF("failed to send rxif configuration\n"); + return LGW_MCU_ERROR; + } + + /* check command acknoledge */ + if (ans.status != ACK_OK) { +- printf("ERROR: rxif configuration, ACK failed\n"); ++ ERROR_PRINTF("rxif configuration, ACK failed\n"); + return LGW_MCU_ERROR; + } + +@@ -273,13 +275,13 @@ int lgw_mcu_txgain_setconf(struct lgw_tx_gain_lut_s *conf) { + /* send command to MCU */ + x = lgw_com_send_command(lgw_com_target, cmd, &ans); + if (x != LGW_COM_SUCCESS) { +- printf("ERROR: failed to send tx gain configuration\n"); ++ ERROR_PRINTF("failed to send tx gain configuration\n"); + return LGW_MCU_ERROR; + } + + /* check command acknoledge */ + if (ans.status != ACK_OK) { +- printf("ERROR: tx gain configuration, ACK failed\n"); ++ ERROR_PRINTF("tx gain configuration, ACK failed\n"); + return LGW_MCU_ERROR; + } + +@@ -310,14 +312,14 @@ int lgw_mcu_receive(uint8_t max_pkt, struct lgw_pkt_rx_s *pkt_data) { + /* send command to MCU */ + x = lgw_com_send_command(lgw_com_target, cmd, &ans); + if ((x != LGW_COM_SUCCESS) || (ans.status != ACK_OK)) { +- DEBUG_MSG("ERROR: failed to receive packets from concentrator\n"); ++ ERROR_PRINTF("failed to receive packets from concentrator\n"); + return 0; + } + + /* check nb_packet variables */ + nb_packet = ans.ans_data[0]; + if ((nb_packet > LGW_PKT_FIFO_SIZE) || (nb_packet < 0)) { +- DEBUG_PRINTF("ERROR: NOT A VALID NUMBER OF RECEIVED PACKET (%d)\n", nb_packet); ++ ERROR_PRINTF("NOT A VALID NUMBER OF RECEIVED PACKET (%d)\n", nb_packet); + return 0; + } + +@@ -434,13 +436,13 @@ int lgw_mcu_send(struct lgw_pkt_tx_s pkt_data) { + /* send command to MCU */ + x = lgw_com_send_command(lgw_com_target, cmd, &ans); + if (x != LGW_COM_SUCCESS) { +- printf("ERROR: failed to send packet\n"); ++ ERROR_PRINTF("failed to send packet\n"); + return LGW_MCU_ERROR; + } + + /* check command acknoledge */ + if (ans.status != ACK_OK) { +- printf("ERROR: failed to send packet, ACK failed\n"); ++ ERROR_PRINTF("failed to send packet, ACK failed\n"); + return LGW_MCU_ERROR; + } + +@@ -466,7 +468,7 @@ int lgw_mcu_get_trigcnt(uint32_t *data) { + /* send command to MCU */ + x = lgw_com_send_command(lgw_com_target, cmd, &ans); + if ((x != LGW_COM_SUCCESS) || (ans.status != ACK_OK)) { +- DEBUG_MSG("ERROR: failed to get concentrator internal counter\n"); ++ ERROR_PRINTF("failed to get concentrator internal counter\n"); + return LGW_MCU_ERROR; + } + +@@ -531,13 +533,13 @@ int lgw_mcu_get_unique_id(uint8_t *uid) { + /* send command to MCU */ + x = lgw_com_send_command(lgw_com_target, cmd, &ans); + if (x != LGW_COM_SUCCESS) { +- DEBUG_MSG("ERROR: Failed to get MCU unique ID\n"); ++ ERROR_PRINTF("Failed to get MCU unique ID\n"); + return LGW_MCU_ERROR; + } + + /* Check MCU FW version */ + if (ans.status == ACK_KO) { +- DEBUG_MSG("ERROR: Invalid MCU firmware version\n"); ++ ERROR_PRINTF("Invalid MCU firmware version\n"); + return LGW_MCU_ERROR; + } + +diff --git a/libloragw/src/loragw_radio.c b/libloragw/src/loragw_radio.c +index 62a80f4..9fd7d2a 100644 +--- a/libloragw/src/loragw_radio.c ++++ b/libloragw/src/loragw_radio.c +@@ -41,6 +41,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + #define CHECK_NULL(a) if(a==NULL){return LGW_REG_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE TYPES -------------------------------------------------------- */ + +@@ -76,11 +78,11 @@ void sx125x_write(uint8_t channel, uint8_t addr, uint8_t data) { + + /* checking input parameters */ + if (channel >= LGW_RF_CHAIN_NB) { +- DEBUG_MSG("ERROR: INVALID RF_CHAIN\n"); ++ ERROR_PRINTF("INVALID RF_CHAIN\n"); + return; + } + if (addr >= 0x7F) { +- DEBUG_MSG("ERROR: ADDRESS OUT OF RANGE\n"); ++ ERROR_PRINTF("ADDRESS OUT OF RANGE\n"); + return; + } + +@@ -99,7 +101,7 @@ void sx125x_write(uint8_t channel, uint8_t addr, uint8_t data) { + break; + + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", channel); ++ ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", channel); + return; + } + +@@ -121,11 +123,11 @@ uint8_t sx125x_read(uint8_t channel, uint8_t addr) { + + /* checking input parameters */ + if (channel >= LGW_RF_CHAIN_NB) { +- DEBUG_MSG("ERROR: INVALID RF_CHAIN\n"); ++ ERROR_PRINTF("INVALID RF_CHAIN\n"); + return 0; + } + if (addr >= 0x7F) { +- DEBUG_MSG("ERROR: ADDRESS OUT OF RANGE\n"); ++ ERROR_PRINTF("ADDRESS OUT OF RANGE\n"); + return 0; + } + +@@ -146,7 +148,7 @@ uint8_t sx125x_read(uint8_t channel, uint8_t addr) { + break; + + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", channel); ++ ERROR_PRINTF("UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", channel); + return 0; + } + +@@ -170,7 +172,7 @@ int lgw_setup_sx125x(uint8_t rf_chain, uint8_t rf_clkout, bool rf_enable, uint8_ + int cpt_attempts = 0; + + if (rf_chain >= LGW_RF_CHAIN_NB) { +- DEBUG_MSG("ERROR: INVALID RF_CHAIN\n"); ++ ERROR_PRINTF("INVALID RF_CHAIN\n"); + return -1; + } + +@@ -194,7 +196,7 @@ int lgw_setup_sx125x(uint8_t rf_chain, uint8_t rf_clkout, bool rf_enable, uint8_ + sx125x_write(rf_chain, 0x26, SX125x_XOSC_GM_STARTUP + SX125x_XOSC_DISABLE * 16); + break; + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type); ++ ERROR_PRINTF("UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type); + break; + } + +@@ -220,7 +222,7 @@ int lgw_setup_sx125x(uint8_t rf_chain, uint8_t rf_clkout, bool rf_enable, uint8_ + part_frac = ((freq_hz % (SX125x_32MHz_FRAC << 8)) << 8) / SX125x_32MHz_FRAC; /* fractional part, gives middle part and LSB */ + break; + default: +- DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type); ++ ERROR_PRINTF("UNEXPECTED VALUE %d FOR RADIO TYPE\n", rf_radio_type); + break; + } + +@@ -231,7 +233,7 @@ int lgw_setup_sx125x(uint8_t rf_chain, uint8_t rf_clkout, bool rf_enable, uint8_ + /* start and PLL lock */ + do { + if (cpt_attempts >= PLL_LOCK_MAX_ATTEMPTS) { +- DEBUG_MSG("ERROR: FAIL TO LOCK PLL\n"); ++ ERROR_PRINTF("FAIL TO LOCK PLL after %d attempts\n", cpt_attempts); + return -1; + } + sx125x_write(rf_chain, 0x00, 1); /* enable Xtal oscillator */ +diff --git a/libloragw/src/loragw_reg.c b/libloragw/src/loragw_reg.c +index 05085bc..8e0338b 100644 +--- a/libloragw/src/loragw_reg.c ++++ b/libloragw/src/loragw_reg.c +@@ -43,6 +43,8 @@ License: Revised BSD License, see LICENSE.TXT file include in the project + #define CHECK_NULL(a) if(a==NULL){return LGW_REG_ERROR;} + #endif + ++#include "loragw_stationlog.h" ++ + /* -------------------------------------------------------------------------- */ + /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + +@@ -429,7 +431,7 @@ int reg_w_align32(void *com_target, uint8_t com_mux_mode, uint8_t com_mux_target + com_stat += lgw_com_wb(com_target, com_mux_mode, com_mux_target, r.addr, buf, size_byte); /* write the register in one burst */ + } else { + /* register spanning multiple memory bytes but with an offset */ +- DEBUG_MSG("ERROR: REGISTER SIZE AND OFFSET ARE NOT SUPPORTED\n"); ++ ERROR_PRINTF("REGISTER SIZE AND OFFSET ARE NOT SUPPORTED\n"); + return LGW_REG_ERROR; + } + +@@ -471,7 +473,7 @@ int reg_r_align32(void *com_target, uint8_t com_mux_mode, uint8_t com_mux_target + } + } else { + /* register spanning multiple memory bytes but with an offset */ +- DEBUG_MSG("ERROR: REGISTER SIZE AND OFFSET ARE NOT SUPPORTED\n"); ++ ERROR_PRINTF("REGISTER SIZE AND OFFSET ARE NOT SUPPORTED\n"); + return LGW_REG_ERROR; + } + +@@ -498,7 +500,7 @@ int lgw_connect(const char *com_path) { + /* open the COM link */ + com_stat = lgw_com_open(&lgw_com_target, com_path); + if (com_stat != LGW_COM_SUCCESS) { +- DEBUG_MSG("ERROR: FAIL TO CONNECT CONCENTRATOR\n"); ++ ERROR_PRINTF("FAIL TO CONNECT CONCENTRATOR\n"); + return LGW_REG_ERROR; + } + +@@ -507,7 +509,7 @@ int lgw_connect(const char *com_path) { + /* check MCU FW version */ + com_stat = lgw_mcu_get_unique_id(&uid[0]); + if (com_stat != LGW_COM_SUCCESS) { +- DEBUG_MSG("ERROR: MCU FW VERSION CHECK FAILED\n"); ++ ERROR_PRINTF("MCU FW VERSION CHECK FAILED\n"); + return LGW_REG_ERROR; + } + +@@ -518,18 +520,18 @@ int lgw_connect(const char *com_path) { + /* check SX1301 version */ + com_stat = lgw_com_r(lgw_com_target, lgw_com_mux_mode, LGW_COM_MUX_TARGET_SX1301, loregs[LGW_VERSION].addr, &u); + if (com_stat != LGW_COM_SUCCESS) { +- DEBUG_MSG("ERROR READING CHIP VERSION REGISTER\n"); ++ ERROR_PRINTF("READING CHIP VERSION REGISTER\n"); + return LGW_REG_ERROR; + } + if (u != loregs[LGW_VERSION].dflt) { +- DEBUG_PRINTF("ERROR: NOT EXPECTED CHIP VERSION (v%u)\n", u); ++ ERROR_PRINTF("NOT EXPECTED CHIP VERSION (v%u)\n", u); + return LGW_REG_ERROR; + } + + /* write 0 to the page/reset register */ + com_stat = lgw_com_w(lgw_com_target, lgw_com_mux_mode, LGW_COM_MUX_TARGET_SX1301, loregs[LGW_PAGE_REG].addr, 0); + if (com_stat != LGW_COM_SUCCESS) { +- DEBUG_MSG("ERROR WRITING PAGE REGISTER\n"); ++ ERROR_PRINTF("WRITING PAGE REGISTER\n"); + return LGW_REG_ERROR; + } else { + lgw_regpage = 0; +@@ -568,7 +570,7 @@ int lgw_disconnect(void) { + int lgw_soft_reset(void) { + /* check if SPI is initialised */ + if ((lgw_com_target == NULL) || (lgw_regpage < 0)) { +- DEBUG_MSG("ERROR: CONCENTRATOR UNCONNECTED\n"); ++ ERROR_PRINTF("CONCENTRATOR UNCONNECTED\n"); + return LGW_REG_ERROR; + } + lgw_com_w(lgw_com_target, lgw_com_mux_mode, LGW_COM_MUX_TARGET_SX1301, 0, 0x80); /* 1 -> SOFT_RESET bit */ +@@ -619,13 +621,13 @@ int lgw_reg_w(uint16_t register_id, int32_t reg_value) { + + /* check input parameters */ + if (register_id >= LGW_TOTALREGS) { +- DEBUG_MSG("ERROR: REGISTER NUMBER OUT OF DEFINED RANGE\n"); ++ ERROR_PRINTF("REGISTER NUMBER OUT OF DEFINED RANGE\n"); + return LGW_REG_ERROR; + } + + /* check if SPI is initialised */ + if ((lgw_com_target == NULL) || (lgw_regpage < 0)) { +- DEBUG_MSG("ERROR: CONCENTRATOR UNCONNECTED\n"); ++ ERROR_PRINTF("CONCENTRATOR UNCONNECTED\n"); + return LGW_REG_ERROR; + } + +@@ -646,7 +648,7 @@ int lgw_reg_w(uint16_t register_id, int32_t reg_value) { + + /* reject write to read-only registers */ + if (r.rdon == 1) { +- DEBUG_MSG("ERROR: TRYING TO WRITE A READ-ONLY REGISTER\n"); ++ ERROR_PRINTF("TRYING TO WRITE A READ-ONLY REGISTER\n"); + return LGW_REG_ERROR; + } + +@@ -658,7 +660,7 @@ int lgw_reg_w(uint16_t register_id, int32_t reg_value) { + com_stat += reg_w_align32(lgw_com_target, lgw_com_mux_mode, LGW_COM_MUX_TARGET_SX1301, r, reg_value); + + if (com_stat != LGW_COM_SUCCESS) { +- DEBUG_MSG("ERROR: SPI ERROR DURING REGISTER WRITE\n"); ++ ERROR_PRINTF("SPI ERROR DURING REGISTER WRITE\n"); + return LGW_REG_ERROR; + } else { + return LGW_REG_SUCCESS; +@@ -675,13 +677,13 @@ int lgw_reg_r(uint16_t register_id, int32_t *reg_value) { + /* check input parameters */ + CHECK_NULL(reg_value); + if (register_id >= LGW_TOTALREGS) { +- DEBUG_MSG("ERROR: REGISTER NUMBER OUT OF DEFINED RANGE\n"); ++ ERROR_PRINTF("REGISTER NUMBER OUT OF DEFINED RANGE\n"); + return LGW_REG_ERROR; + } + + /* check if SPI is initialised */ + if ((lgw_com_target == NULL) || (lgw_regpage < 0)) { +- DEBUG_MSG("ERROR: CONCENTRATOR UNCONNECTED\n"); ++ ERROR_PRINTF("CONCENTRATOR UNCONNECTED\n"); + return LGW_REG_ERROR; + } + +@@ -696,7 +698,7 @@ int lgw_reg_r(uint16_t register_id, int32_t *reg_value) { + com_stat += reg_r_align32(lgw_com_target, lgw_com_mux_mode, LGW_COM_MUX_TARGET_SX1301, r, reg_value); + + if (com_stat != LGW_COM_SUCCESS) { +- DEBUG_MSG("ERROR: SPI ERROR DURING REGISTER WRITE\n"); ++ ERROR_PRINTF("SPI ERROR DURING REGISTER WRITE\n"); + return LGW_REG_ERROR; + } else { + return LGW_REG_SUCCESS; +@@ -713,17 +715,17 @@ int lgw_reg_wb(uint16_t register_id, uint8_t *data, uint16_t size) { + /* check input parameters */ + CHECK_NULL(data); + if (size == 0) { +- DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); ++ ERROR_PRINTF("BURST OF NULL LENGTH\n"); + return LGW_REG_ERROR; + } + if (register_id >= LGW_TOTALREGS) { +- DEBUG_MSG("ERROR: REGISTER NUMBER OUT OF DEFINED RANGE\n"); ++ ERROR_PRINTF("REGISTER NUMBER OUT OF DEFINED RANGE\n"); + return LGW_REG_ERROR; + } + + /* check if SPI is initialised */ + if ((lgw_com_target == NULL) || (lgw_regpage < 0)) { +- DEBUG_MSG("ERROR: CONCENTRATOR UNCONNECTED\n"); ++ ERROR_PRINTF("CONCENTRATOR UNCONNECTED\n"); + return LGW_REG_ERROR; + } + +@@ -732,7 +734,7 @@ int lgw_reg_wb(uint16_t register_id, uint8_t *data, uint16_t size) { + + /* reject write to read-only registers */ + if (r.rdon == 1) { +- DEBUG_MSG("ERROR: TRYING TO BURST WRITE A READ-ONLY REGISTER\n"); ++ ERROR_PRINTF("TRYING TO BURST WRITE A READ-ONLY REGISTER\n"); + return LGW_REG_ERROR; + } + +@@ -745,7 +747,7 @@ int lgw_reg_wb(uint16_t register_id, uint8_t *data, uint16_t size) { + com_stat += lgw_com_wb(lgw_com_target, lgw_com_mux_mode, LGW_COM_MUX_TARGET_SX1301, r.addr, data, size); + + if (com_stat != LGW_COM_SUCCESS) { +- DEBUG_MSG("ERROR: SPI ERROR DURING REGISTER BURST WRITE\n"); ++ ERROR_PRINTF("SPI ERROR DURING REGISTER BURST WRITE\n"); + return LGW_REG_ERROR; + } else { + return LGW_REG_SUCCESS; +@@ -762,17 +764,17 @@ int lgw_reg_rb(uint16_t register_id, uint8_t *data, uint16_t size) { + /* check input parameters */ + CHECK_NULL(data); + if (size == 0) { +- DEBUG_MSG("ERROR: BURST OF NULL LENGTH\n"); ++ ERROR_PRINTF("BURST OF NULL LENGTH\n"); + return LGW_REG_ERROR; + } + if (register_id >= LGW_TOTALREGS) { +- DEBUG_MSG("ERROR: REGISTER NUMBER OUT OF DEFINED RANGE\n"); ++ ERROR_PRINTF("REGISTER NUMBER OUT OF DEFINED RANGE\n"); + return LGW_REG_ERROR; + } + + /* check if SPI is initialised */ + if ((lgw_com_target == NULL) || (lgw_regpage < 0)) { +- DEBUG_MSG("ERROR: CONCENTRATOR UNCONNECTED\n"); ++ ERROR_PRINTF("CONCENTRATOR UNCONNECTED\n"); + return LGW_REG_ERROR; + } + +@@ -788,7 +790,7 @@ int lgw_reg_rb(uint16_t register_id, uint8_t *data, uint16_t size) { + com_stat += lgw_com_rb(lgw_com_target, lgw_com_mux_mode, LGW_COM_MUX_TARGET_SX1301, r.addr, data, size); + + if (com_stat != LGW_COM_SUCCESS) { +- DEBUG_MSG("ERROR: SPI ERROR DURING REGISTER BURST READ\n"); ++ ERROR_PRINTF("SPI ERROR DURING REGISTER BURST READ\n"); + return LGW_REG_ERROR; + } else { + return LGW_REG_SUCCESS; diff --git a/deps/smtcpico/makefile b/deps/smtcpico/makefile index 0afa8d3..2dfa12a 100644 --- a/deps/smtcpico/makefile +++ b/deps/smtcpico/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -35,9 +35,11 @@ LGWVERSION.default = 0.2.2 LGWVERSION ?= $(or ${LGWVERSION.${platform}}, ${LGWVERSION.default}) HFILES = $(wildcard ${PLT}/libloragw/inc/*.h) -SRCS = $(wildcard ${PLT}/libloragw/inc/*.c) +SRCS = $(wildcard ${PLT}/libloragw/src/*.c) ARTEFACTS = ${LGWLIB} ${LGWINC} $(patsubst %, ${LGWINC}/%, $(notdir ${HFILES}) config.h) +LGW_EXTRA_CFLAGS = -DSTATIONLOG # Enable station log integration + all: $(if ${HFILES},${ARTEFACTS},${PLT}) ${LGWINC}: @@ -49,10 +51,10 @@ ${LGWLIB}: ${PLT}/libloragw/libloragw.a @cp $< $@ ${PLT}/libloragw/libloragw.a: ${SRCS} ${HFILES} - ${MAKE} -C ${PLT}/libloragw libloragw.a CC=${CC} AR=${AR} LD=${LD} TDfull=${TDfull} + ${MAKE} -C ${PLT}/libloragw libloragw.a CC="${CC}" AR="${AR}" LD="${LD}" TDfull="${TDfull}" EXTRA_CFLAGS="${LGW_EXTRA_CFLAGS}" ${PLT}/libloragw/inc/config.h: ${PLT}/libloragw/library.cfg - ${MAKE} -C ${PLT}/libloragw inc/config.h CC=${CC} AR=${AR} LD=${LD} TDfull=${TDfull} + ${MAKE} -C ${PLT}/libloragw inc/config.h CC="${CC}" AR="${AR}" LD="${LD}" TDfull="${TDfull}" ${LGWINC}/%.h: ${PLT}/libloragw/inc/%.h | ${LGWINC} @echo " CP ${ $@" diff --git a/deps/smtcpico/prep.sh b/deps/smtcpico/prep.sh index a531660..91b14a2 100755 --- a/deps/smtcpico/prep.sh +++ b/deps/smtcpico/prep.sh @@ -1,7 +1,7 @@ #!/bin/bash # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/examples/corecell/start-station.sh b/examples/corecell/start-station.sh index 5317c19..5800495 100755 --- a/examples/corecell/start-station.sh +++ b/examples/corecell/start-station.sh @@ -1,7 +1,7 @@ #!/bin/sh # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/examples/cups/emulate.sh b/examples/cups/emulate.sh index bdcf998..6ef140a 100755 --- a/examples/cups/emulate.sh +++ b/examples/cups/emulate.sh @@ -1,7 +1,7 @@ #!/bin/bash # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/examples/cups/makefile b/examples/cups/makefile index 8487192..63a3dca 100644 --- a/examples/cups/makefile +++ b/examples/cups/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/examples/cups/prep.sh b/examples/cups/prep.sh index f7e3209..d6c4871 100755 --- a/examples/cups/prep.sh +++ b/examples/cups/prep.sh @@ -1,7 +1,7 @@ #!/bin/bash # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/examples/cups/requirements.txt b/examples/cups/requirements.txt index dfb9d2c..9142b67 100644 --- a/examples/cups/requirements.txt +++ b/examples/cups/requirements.txt @@ -1,2 +1,2 @@ -aiohttp==3.5.1 -websockets==6.0 +aiohttp==3.8.1 +websockets==10.1 diff --git a/examples/cups/sim.py b/examples/cups/sim.py index bd0d011..58044e6 100644 --- a/examples/cups/sim.py +++ b/examples/cups/sim.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/examples/live-s2.sm.tc/makefile b/examples/live-s2.sm.tc/makefile index 80fce24..cb8cc3c 100644 --- a/examples/live-s2.sm.tc/makefile +++ b/examples/live-s2.sm.tc/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/examples/simulation/makefile b/examples/simulation/makefile index 51da284..3a2b900 100644 --- a/examples/simulation/makefile +++ b/examples/simulation/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/examples/simulation/requirements.txt b/examples/simulation/requirements.txt index dfb9d2c..9142b67 100644 --- a/examples/simulation/requirements.txt +++ b/examples/simulation/requirements.txt @@ -1,2 +1,2 @@ -aiohttp==3.5.1 -websockets==6.0 +aiohttp==3.8.1 +websockets==10.1 diff --git a/examples/simulation/sim.py b/examples/simulation/sim.py index 07de890..833fe3a 100644 --- a/examples/simulation/sim.py +++ b/examples/simulation/sim.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/examples/station2pkfwd/bgtask.py b/examples/station2pkfwd/bgtask.py index a676301..a9a946b 100644 --- a/examples/station2pkfwd/bgtask.py +++ b/examples/station2pkfwd/bgtask.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/examples/station2pkfwd/id6.py b/examples/station2pkfwd/id6.py index 8fab414..6d8bce6 100644 --- a/examples/station2pkfwd/id6.py +++ b/examples/station2pkfwd/id6.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/examples/station2pkfwd/main.py b/examples/station2pkfwd/main.py index a4cc073..d0ce661 100644 --- a/examples/station2pkfwd/main.py +++ b/examples/station2pkfwd/main.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/examples/station2pkfwd/pkfwdc.py b/examples/station2pkfwd/pkfwdc.py index 51111ce..5023fed 100644 --- a/examples/station2pkfwd/pkfwdc.py +++ b/examples/station2pkfwd/pkfwdc.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/examples/station2pkfwd/requirements.txt b/examples/station2pkfwd/requirements.txt index a7c083b..dbc994f 100644 --- a/examples/station2pkfwd/requirements.txt +++ b/examples/station2pkfwd/requirements.txt @@ -1,2 +1,2 @@ -websockets==6.0 -PyYAML==5.1 +websockets==10.1 +PyYAML==6.0 diff --git a/examples/station2pkfwd/router.py b/examples/station2pkfwd/router.py index 08137b3..a985ff2 100644 --- a/examples/station2pkfwd/router.py +++ b/examples/station2pkfwd/router.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/examples/station2pkfwd/router_config.py b/examples/station2pkfwd/router_config.py index fd8193b..e06f673 100644 --- a/examples/station2pkfwd/router_config.py +++ b/examples/station2pkfwd/router_config.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/makefile b/makefile index 3530e4e..2583a7b 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/makefile.s2core b/makefile.s2core index 259a7be..84a4da0 100644 --- a/makefile.s2core +++ b/makefile.s2core @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/pysys/id6.py b/pysys/id6.py index 3e6d4d6..ce6f67c 100644 --- a/pysys/id6.py +++ b/pysys/id6.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/pysys/simutils.py b/pysys/simutils.py index d766ad5..5694977 100644 --- a/pysys/simutils.py +++ b/pysys/simutils.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/pysys/tcutils.py b/pysys/tcutils.py index bd134b2..f6466d9 100644 --- a/pysys/tcutils.py +++ b/pysys/tcutils.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -48,7 +48,7 @@ base_regions = { "EU863" : { 'msgtype': 'router_config', - 'region': 'EU863', + 'region': 'EU868', 'DRs': [(12, 125, 0), (11, 125, 0), (10, 125, 0), @@ -71,7 +71,7 @@ }, "US902": { 'msgtype': 'router_config', - 'region': 'US902', + 'region': 'US915', 'DRs': [(10, 125, 0), (9, 125, 0), (8, 125, 0), @@ -111,7 +111,7 @@ 'config': {}, 'hwspec': 'sx1301/1', 'sx1301_conf': [{'chan_FSK': {'enable': False}, - 'chan_Lora_std': {'enable': False}, + 'chan_Lora_std': {'enable': False}, 'chan_multiSF_0': {'enable': True, 'if': -375000, 'radio': 0}, 'chan_multiSF_1': {'enable': True, 'if': -175000, 'radio': 0}, 'chan_multiSF_2': {'enable': True, 'if': 25000, 'radio': 0}, @@ -231,7 +231,7 @@ async def handle_ws(self, ws, path): try: while True: msg = json.loads(await ws.recv()) - logger.debug('> INFOS: %r' % msg); + logger.debug('> INFOS: %r' % msg) r = msg['router'] resp = { 'router': r, @@ -240,14 +240,14 @@ async def handle_ws(self, ws, path): } resp = self.router_info_response(resp) await ws.send(json.dumps(resp)) - logger.debug('< INFOS: %r' % resp); + logger.debug('< INFOS: %r' % resp) except websockets.exceptions.ConnectionClosed as exc: if exc.code != 1000: logger.error('x INFOS close: code=%d reason=%r', exc.code, exc.reason) except Exception as exc: logger.error('x INFOS exception: %s', exc, exc_info=True) try: - ws.close() + await ws.close() except: pass @@ -370,6 +370,13 @@ def rdPEM(self, fn, fmt="PEM"): with open(fn,'rb') as f: return self.normalizePEM(f.read(), fmt)[0] + def rdToken(self, fn): + if not os.path.exists(fn): + return b'\x00'*4 + with open(fn,'rb') as f: + token = f.read().decode('ascii') + return token.strip().encode('ascii') + b'\r\n' + def normalizeId (self, id:Any) -> str: # For tests use a shorter representation # For production use str(Id6(id)) @@ -381,9 +388,15 @@ def readCupsCred(self, routerid, cupsid, fmt="PEM"): self.rdPEM('%s/cups-router-%s.key' % (cupsid,routerid), fmt)) def readTcCred(self, routerid, fmt="PEM"): - return (self.rdPEM('%s/tc.ca' % self.tcdir, fmt) + - self.rdPEM('%s/tc-router-%s.crt' % (self.tcdir,routerid), fmt) + - self.rdPEM('%s/tc-router-%s.key' % (self.tcdir,routerid), fmt)) + tcTrust = self.rdPEM('%s/tc-router-%s.trust' % (self.tcdir,routerid), fmt) + if tcTrust == b'\x00\x00\x00\x00': + tcTrust = self.rdPEM('%s/tc.ca' % self.tcdir, fmt) + tcCert = self.rdPEM('%s/tc-router-%s.crt' % (self.tcdir,routerid), fmt) + if tcCert == b'\x00\x00\x00\x00': + tcKey = self.rdToken('%s/tc-router-%s.key' % (self.tcdir,routerid)) + else: + tcKey = self.rdPEM('%s/tc-router-%s.key' % (self.tcdir,routerid), fmt) + return tcTrust + tcCert + tcKey def readRouterConfig(self, id:str) -> Dict[str,Any]: with open('%s/cups-router-%s.cfg' % (self.homedir, id) ) as f: @@ -462,7 +475,7 @@ def on_response(self, r_cupsUri:bytes, r_tcUri:bytes, r_cupsCred:bytes, r_tcCred async def handle_update_info(self, request) -> web.Response: req = await request.json() - logger.debug('> CUPS Request: %r' % req); + logger.debug('> CUPS Request: %r' % req) routerid = self.normalizeId(req['router']) cfg = self.readRouterConfig(routerid) @@ -503,3 +516,4 @@ async def handle_update_info(self, request) -> web.Response: body = self.on_response(r_cupsUri, r_tcUri, r_cupsCred, r_tcCred, r_sig, r_fwbin) return web.Response(body=body) + diff --git a/pysys/testutils.py b/pysys/testutils.py index ed557e7..ece0220 100644 --- a/pysys/testutils.py +++ b/pysys/testutils.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/makefile b/regr-tests/makefile index 84cd456..206f78e 100644 --- a/regr-tests/makefile +++ b/regr-tests/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -29,8 +29,13 @@ INFOS=$(shell find . -name 'test*.info') all: ./run-regression-tests --nohw +# teirich: my VM is a bit slow causing some TX to miss the deadline. +# Cut the tests some slack... +slow-vm: + TX_AIM_GAP='"40ms"' PPSTHRES=300 ./run-regression-tests --nohw + ci: - ./run-regression-tests --nohw --verbose --travis + ./run-regression-tests --nohw --verbose --ghactions # Reset test state reset: @@ -38,10 +43,12 @@ reset: # Pack all info files together into a single report s2core.info: ${INFOS} + @echo "::group::Generate coverage report" lcov -t "s2core" $(patsubst %, -a %, ${INFOS}) -o temp1.info genhtml -o s2core-html temp1.info # lcov -r temp.info '*/test.c' '*/log.c' -o temp.2.info # rm temp.info + @echo "::endgroup::" lcov -l temp1.info # We're not close to 100% currently # lcov -l temp.2.info | grep -P 'Total:.\s+100%\s+\d+.\s+100%\s+' diff --git a/regr-tests/run-regression-tests b/regr-tests/run-regression-tests index 9a56782..530feb0 100755 --- a/regr-tests/run-regression-tests +++ b/regr-tests/run-regression-tests @@ -1,7 +1,7 @@ #!/bin/bash # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -41,7 +41,7 @@ verbose=0 nohw=0 forcebuild=0 cleanrun=0 -travis=0 +ghactions=0 export IGNORE="livecups" @@ -51,7 +51,10 @@ while [ "$1" != "" ]; do -n | --nohw ) export IGNORE="-hw$|$IGNORE";; -b | --build ) forcebuild=1 ;; -c | --clean ) cleanrun=1 ;; - -t | --travis ) travis=1 ;; + -g | --ghactions ) ghactions=1 ;; + -T* ) tests="${1#-T}";; + --tests=* ) tests="${1#--tests=}";; + *) echo "Illegal argument: $1" >&2; exit 1;; esac shift done @@ -61,10 +64,10 @@ btarget="" [[ $forcebuild -eq 1 ]] && btarget="deps s-clean s-all" # Make sure variants are up-to-date for variant in $variants; do - [[ $travis -eq 1 ]] && echo "travis_fold:start:build.$variant" + [[ $ghactions -eq 1 ]] && echo "::group::Build $variant" echo "Build $variant" variant=$variant make -C .. $btarget - [[ $travis -eq 1 ]] && echo "travis_fold:end:build.$variant" + [[ $ghactions -eq 1 ]] && echo "::endgroup::" done set +e @@ -108,8 +111,8 @@ for testdir in $tests; do fi beg=$(date +%s) f="tlog/$test.log" - if [[ $travis -eq 1 ]]; then - echo "travis_fold:start:$test" + if [[ $ghactions -eq 1 ]]; then + echo "::group::$test" echo "Running $test" else echo -ne "Running $test...\r" @@ -118,13 +121,13 @@ for testdir in $tests; do if [[ "$IGNORE" != "" ]] && [[ "$testdir" =~ $IGNORE ]]; then echo "--- Test N/A ---" > "$tfile" elif [[ $verbose -eq 1 ]]; then - TEST_VARIANT=$variant make -C $testdir | tee "$tfile" 2>&1 + TEST_VARIANT=$variant make -C $testdir 2>&1 | tee "$tfile" else TEST_VARIANT=$variant make -C $testdir >"$tfile" 2>&1 fi xcode=$? set +o pipefail - [[ $travis -eq 1 ]] && echo "travis_fold:end:$test" + [[ $ghactions -eq 1 ]] && echo "::endgroup::" end=$(date +%s) mins=$(printf "[%3dsecs]" $(($end-$beg))) if grep -- "--- Test N/A ---" "$tfile" >/dev/null 2>&1; then diff --git a/regr-tests/test1-selftests/makefile b/regr-tests/test1-selftests/makefile index b79c084..aaf5a8c 100644 --- a/regr-tests/test1-selftests/makefile +++ b/regr-tests/test1-selftests/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test1-selftests/test.sh b/regr-tests/test1-selftests/test.sh index 1aee44a..6122eb3 100755 --- a/regr-tests/test1-selftests/test.sh +++ b/regr-tests/test1-selftests/test.sh @@ -1,7 +1,7 @@ #!/bin/bash # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test2-fs/makefile b/regr-tests/test2-fs/makefile index b79c084..aaf5a8c 100644 --- a/regr-tests/test2-fs/makefile +++ b/regr-tests/test2-fs/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test2-fs/test.sh b/regr-tests/test2-fs/test.sh index b7e8515..8953434 100755 --- a/regr-tests/test2-fs/test.sh +++ b/regr-tests/test2-fs/test.sh @@ -1,7 +1,7 @@ #!/bin/bash # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test2-gps/makefile b/regr-tests/test2-gps/makefile index b79c084..aaf5a8c 100644 --- a/regr-tests/test2-gps/makefile +++ b/regr-tests/test2-gps/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test2-gps/test.py b/regr-tests/test2-gps/test.py index b49dddf..9800efd 100644 --- a/regr-tests/test2-gps/test.py +++ b/regr-tests/test2-gps/test.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -64,7 +64,11 @@ async def testDone(self, status): station = None os._exit(status) + async def handle_event(self, ws, msg): + logger.debug('EVENT: %r', msg) + async def handle_alarm(self, ws, msg): + logger.debug('ALARM: %r', msg) text = msg['text'] if 'GPS' in text: self.gpscnt += 1 @@ -103,9 +107,13 @@ async def test_start(): logger.debug('Writing GPGGA...') fixquality = (i&4)*2 # 4x 0 then 4x 2 lat = b'00849.8387' if i&1 else b'00848.8387' - f.write(nmea_cksum(b'GPGGA,165848.000,4714.7671,N,%s,E,%d,9,1.01,480.0,M,48.0,M,0000,0000' % (lat, fixquality))) - logger.debug('Writing cmd.fifo...') + sentence = nmea_cksum(b'GPGGA,165848.000,4714.7671,N,%s,E,%d,9,1.01,480.0,M,48.0,M,0000,0000' % (lat, fixquality)) + f.write(sentence) + logger.debug('Writing cmd.fifo: %s' % (sentence[:-2].decode('ascii'),)) c.write(b'{"msgtype":"alarm","text":"CMD test no.%d"}\n' % (i,)) + sentence = nmea_cksum(b'GPGGA,165848.001,,,,,0,00,99.99,,,,,,') + f.write(sentence) + logger.debug('Writing cmd.fifo: %s' % (sentence[:-2].decode('ascii'),)) await asyncio.sleep(1) notok = 1 logger.debug('gpscnt=%d gpsmove=%d gpsnofix=%d cmdcnt=%d' % (muxs.gpscnt, muxs.gpsmove, muxs.gpsnofix, muxs.cmdcnt)) diff --git a/regr-tests/test2-gps/test.sh b/regr-tests/test2-gps/test.sh index a06364a..878caac 100755 --- a/regr-tests/test2-gps/test.sh +++ b/regr-tests/test2-gps/test.sh @@ -1,7 +1,7 @@ #!/bin/bash # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test2-pps/makefile b/regr-tests/test2-pps/makefile index b79c084..aaf5a8c 100644 --- a/regr-tests/test2-pps/makefile +++ b/regr-tests/test2-pps/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test2-pps/test.py b/regr-tests/test2-pps/test.py index ffba6f4..03f748f 100644 --- a/regr-tests/test2-pps/test.py +++ b/regr-tests/test2-pps/test.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -55,12 +55,14 @@ class TestMuxs(tu.Muxs): tscnt = 0 first = None - async def testDone(self, status): + async def testDone(self, status, msg=''): global station if station: station.terminate() await station.wait() station = None + if status: + print(f'TEST FAILED code={status} ({msg})', file=sys.stderr) os._exit(status) async def handle_timesync(self, ws, msg): @@ -82,8 +84,8 @@ async def handle_alarm(self, ws, msg): async def timeout(): - await asyncio.sleep(20) - await muxs.testDone(2) + await asyncio.sleep(50) + await muxs.testDone(2, 'TIMEOUT') async def test_start(): diff --git a/regr-tests/test2-pps/test.sh b/regr-tests/test2-pps/test.sh index e21e642..e55f823 100755 --- a/regr-tests/test2-pps/test.sh +++ b/regr-tests/test2-pps/test.sh @@ -1,7 +1,7 @@ #!/bin/bash # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test3-updn-tls/makefile b/regr-tests/test3-updn-tls/makefile index b79c084..aaf5a8c 100644 --- a/regr-tests/test3-updn-tls/makefile +++ b/regr-tests/test3-updn-tls/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test3-updn-tls/test.py b/regr-tests/test3-updn-tls/test.py index 0eb2dad..6f0ab86 100644 --- a/regr-tests/test3-updn-tls/test.py +++ b/regr-tests/test3-updn-tls/test.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -82,7 +82,7 @@ async def send_updf(self) -> None: lgwsim = self.units[0] await lgwsim.send_rx(rps=(7,125), freq=freq, frame=su.makeDF(fcnt=self.fcnt, port=port)) self.fcnt += 1 - await asyncio.sleep(1.0) + await asyncio.sleep(2.5) except asyncio.CancelledError: logger.debug('send_updf canceled.') except Exception as exc: @@ -101,9 +101,13 @@ async def testDone(self, status): os._exit(status) async def handle_dntxed(self, ws, msg): - if [msg['seqno']] != self.exp_seqno[0:1]: - logger.error('DNTXED: %r\nbut expected seqno=%r' % (msg, self.exp_seqno)) + seqno = msg['seqno'] + if seqno != msg['diid']: + await self.testDone(3) + if [seqno] != self.exp_seqno[0:1]: + logger.error('DNTXED: %r but expected seqno=%r\n\t=>%r', seqno, self.exp_seqno, msg) await self.testDone(2) + logger.debug('DNTXED: %r and expected seqno=%r', seqno, self.exp_seqno) del self.exp_seqno[0] async def handle_updf(self, ws, msg): diff --git a/regr-tests/test3-updn-tls/test.sh b/regr-tests/test3-updn-tls/test.sh index 2f7f283..8ebfe8f 100755 --- a/regr-tests/test3-updn-tls/test.sh +++ b/regr-tests/test3-updn-tls/test.sh @@ -1,7 +1,7 @@ #!/bin/bash # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test3a-updn-tls/makefile b/regr-tests/test3a-updn-tls/makefile index b79c084..aaf5a8c 100644 --- a/regr-tests/test3a-updn-tls/makefile +++ b/regr-tests/test3a-updn-tls/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test3a-updn-tls/test.py b/regr-tests/test3a-updn-tls/test.py index 97694bd..6334472 100644 --- a/regr-tests/test3a-updn-tls/test.py +++ b/regr-tests/test3a-updn-tls/test.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -82,7 +82,7 @@ async def send_updf(self) -> None: lgwsim = self.units[0] await lgwsim.send_rx(rps=(7,125), freq=freq, frame=su.makeDF(fcnt=self.fcnt, port=port)) self.fcnt += 1 - await asyncio.sleep(1.0) + await asyncio.sleep(2.0) except asyncio.CancelledError: logger.debug('send_updf canceled.') except Exception as exc: @@ -101,9 +101,13 @@ async def testDone(self, status): os._exit(status) async def handle_dntxed(self, ws, msg): - if [msg['seqno']] != self.exp_seqno[0:1]: - logger.error('DNTXED: %r\nbut expected seqno=%r' % (msg, self.exp_seqno)) + seqno = msg['seqno'] + if seqno != msg['diid']: + await self.testDone(3) + if [seqno] != self.exp_seqno[0:1]: + logger.error('DNTXED: %r but expected seqno=%r\n\t=> %r', seqno, self.exp_seqno, msg) await self.testDone(2) + logger.debug('DNTXED: got %r of expected %r', seqno, self.exp_seqno) del self.exp_seqno[0] async def handle_updf(self, ws, msg): diff --git a/regr-tests/test3a-updn-tls/test.sh b/regr-tests/test3a-updn-tls/test.sh index 4b7d7f1..22a9346 100755 --- a/regr-tests/test3a-updn-tls/test.sh +++ b/regr-tests/test3a-updn-tls/test.sh @@ -1,7 +1,7 @@ #!/bin/bash # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test3b-dnC/makefile b/regr-tests/test3b-dnC/makefile index b79c084..aaf5a8c 100644 --- a/regr-tests/test3b-dnC/makefile +++ b/regr-tests/test3b-dnC/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test3b-dnC/test.py b/regr-tests/test3b-dnC/test.py index 6e7f3e6..a76796f 100644 --- a/regr-tests/test3b-dnC/test.py +++ b/regr-tests/test3b-dnC/test.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -97,9 +97,10 @@ def make_dnmsgC(self, rx2dr=0, rx2freq=869.525, plen=5): return dnmsg async def send_classC(self): + # Wait a while until station has synced time with SX130x + # otherwise class C gets rejected + await asyncio.sleep(3.0) try: - await asyncio.sleep(1.0) - dnmsg1 = self.make_dnmsgC(rx2dr=0, plen=20) # airtime: 1.3s dnmsg2 = self.make_dnmsgC(rx2dr=0, plen=20) # cannot be sent - blocked previous (for 1s) self.exp_seqno.append(dnmsg1['seqno']) diff --git a/regr-tests/test3b-dnC/test.sh b/regr-tests/test3b-dnC/test.sh index c468155..6bbcff1 100755 --- a/regr-tests/test3b-dnC/test.sh +++ b/regr-tests/test3b-dnC/test.sh @@ -1,7 +1,7 @@ #!/bin/bash # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test3b-dnC_2ant/makefile b/regr-tests/test3b-dnC_2ant/makefile index b79c084..aaf5a8c 100644 --- a/regr-tests/test3b-dnC_2ant/makefile +++ b/regr-tests/test3b-dnC_2ant/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test3b-dnC_2ant/test.py b/regr-tests/test3b-dnC_2ant/test.py index df6c335..519d468 100644 --- a/regr-tests/test3b-dnC_2ant/test.py +++ b/regr-tests/test3b-dnC_2ant/test.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -112,6 +112,9 @@ async def send_classC_seq(self, dnmsgs, exp): async def send_classC(self): + # Wait a while until station has synced time with SX130x + # otherwise class C gets rejected + await asyncio.sleep(3.0) try: if n_ant == 2 and omni: dnmsgs = [ diff --git a/regr-tests/test3b-dnC_2ant/test.sh b/regr-tests/test3b-dnC_2ant/test.sh index eed3926..6b86816 100755 --- a/regr-tests/test3b-dnC_2ant/test.sh +++ b/regr-tests/test3b-dnC_2ant/test.sh @@ -1,7 +1,7 @@ #!/bin/bash # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test3b-rx2_2ant/makefile b/regr-tests/test3b-rx2_2ant/makefile index b79c084..aaf5a8c 100644 --- a/regr-tests/test3b-rx2_2ant/makefile +++ b/regr-tests/test3b-rx2_2ant/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test3b-rx2_2ant/test.py b/regr-tests/test3b-rx2_2ant/test.py index 8a510aa..5589b0b 100644 --- a/regr-tests/test3b-rx2_2ant/test.py +++ b/regr-tests/test3b-rx2_2ant/test.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test3b-rx2_2ant/test.sh b/regr-tests/test3b-rx2_2ant/test.sh index e950a08..216d782 100755 --- a/regr-tests/test3b-rx2_2ant/test.sh +++ b/regr-tests/test3b-rx2_2ant/test.sh @@ -1,7 +1,7 @@ #!/bin/bash # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test3c-cca/makefile b/regr-tests/test3c-cca/makefile index b79c084..aaf5a8c 100644 --- a/regr-tests/test3c-cca/makefile +++ b/regr-tests/test3c-cca/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test3c-cca/test.py b/regr-tests/test3c-cca/test.py index 6e6eabb..4dbfde0 100644 --- a/regr-tests/test3c-cca/test.py +++ b/regr-tests/test3c-cca/test.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -133,8 +133,10 @@ def make_dnmsgC(self, rx2dr=4, rx2freq=FREQ1, plen=12): return dnmsg async def send_classC(self): + # Wait a while until station has synced time with SX130x + # otherwise class C gets rejected + await asyncio.sleep(3.0) try: - await asyncio.sleep(1.0) assert self.seqno & 1 == 0 for f in (FREQ1,FREQ2,FREQ3,FREQ2): diff --git a/regr-tests/test3c-cca/test.sh b/regr-tests/test3c-cca/test.sh index c468155..6bbcff1 100755 --- a/regr-tests/test3c-cca/test.sh +++ b/regr-tests/test3c-cca/test.sh @@ -1,7 +1,7 @@ #!/bin/bash # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test3d-bcns/makefile b/regr-tests/test3d-bcns/makefile index b79c084..aaf5a8c 100644 --- a/regr-tests/test3d-bcns/makefile +++ b/regr-tests/test3d-bcns/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test3d-bcns/test.py b/regr-tests/test3d-bcns/test.py index bda2275..79f23e6 100644 --- a/regr-tests/test3d-bcns/test.py +++ b/regr-tests/test3d-bcns/test.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -47,6 +47,7 @@ REGION = os.environ.get('REGION','KR920') PPM = 1000000 BINTV = 2 +PPSTHRES = 10 # measure for timing accuracy of test/sim platform class TestLgwSimServer(su.LgwSimServer): fcnt = 0 @@ -79,7 +80,7 @@ async def on_tx(self, lgwsim, pkt): logger.debug('LGWSIM: ON_GPS %r', pkt) d = utc % PPM if d >= PPM//2: d -= PPM - assert abs(d) < 10 + assert abs(d) < PPSTHRES, f'Failed abs(d)={abs(d)} < PPSTHRES={PPSTHRES}' assert (utc - d) % PPM == 0 secs = (utc - d) // PPM assert self.last_secs==0 or self.last_secs+BINTV == secs @@ -198,6 +199,8 @@ async def handle_dntxed(self, ws, msg): #XXX:old: logger.error('send_classC failed: %s', exc, exc_info=True) #XXX:old: await self.testDone(1) +if 'PPSTHRES' in os.environ: + PPSTHRES = int(os.environ['PPSTHRES']) with open("tc.uri","w") as f: f.write('ws://localhost:6038') diff --git a/regr-tests/test3d-bcns/test.sh b/regr-tests/test3d-bcns/test.sh index d1d89d6..9097498 100755 --- a/regr-tests/test3d-bcns/test.sh +++ b/regr-tests/test3d-bcns/test.sh @@ -1,7 +1,7 @@ #!/bin/bash # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test4-cups/makefile b/regr-tests/test4-cups/makefile index 9448175..f7c1c15 100644 --- a/regr-tests/test4-cups/makefile +++ b/regr-tests/test4-cups/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test4-cups/test.py b/regr-tests/test4-cups/test.py index 71a30ae..06358a1 100644 --- a/regr-tests/test4-cups/test.py +++ b/regr-tests/test4-cups/test.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test4-cups/test.sh b/regr-tests/test4-cups/test.sh index 23da4af..879c8b8 100755 --- a/regr-tests/test4-cups/test.sh +++ b/regr-tests/test4-cups/test.sh @@ -1,7 +1,7 @@ #!/bin/bash # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test5-rmtsh/makefile b/regr-tests/test5-rmtsh/makefile index b79c084..aaf5a8c 100644 --- a/regr-tests/test5-rmtsh/makefile +++ b/regr-tests/test5-rmtsh/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test5-rmtsh/test.py b/regr-tests/test5-rmtsh/test.py index 4a98b0e..0a1fa7a 100644 --- a/regr-tests/test5-rmtsh/test.py +++ b/regr-tests/test5-rmtsh/test.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test5-rmtsh/test.sh b/regr-tests/test5-rmtsh/test.sh index 40e0a8c..e2150d0 100755 --- a/regr-tests/test5-rmtsh/test.sh +++ b/regr-tests/test5-rmtsh/test.sh @@ -1,7 +1,7 @@ #!/bin/bash # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test5-runcmd/makefile b/regr-tests/test5-runcmd/makefile index b79c084..aaf5a8c 100644 --- a/regr-tests/test5-runcmd/makefile +++ b/regr-tests/test5-runcmd/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test5-runcmd/test.py b/regr-tests/test5-runcmd/test.py index 9c20f42..78ffc9a 100644 --- a/regr-tests/test5-runcmd/test.py +++ b/regr-tests/test5-runcmd/test.py @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test5-runcmd/test.sh b/regr-tests/test5-runcmd/test.sh index 8e506f9..2dc4f33 100755 --- a/regr-tests/test5-runcmd/test.sh +++ b/regr-tests/test5-runcmd/test.sh @@ -1,7 +1,7 @@ #!/bin/bash # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test7-respawn/makefile b/regr-tests/test7-respawn/makefile index be592b7..26370b9 100644 --- a/regr-tests/test7-respawn/makefile +++ b/regr-tests/test7-respawn/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test7-respawn/test.sh b/regr-tests/test7-respawn/test.sh index 3a16cfc..4be66f8 100755 --- a/regr-tests/test7-respawn/test.sh +++ b/regr-tests/test7-respawn/test.sh @@ -1,7 +1,7 @@ #!/bin/bash # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test8-web/makefile b/regr-tests/test8-web/makefile index be592b7..26370b9 100644 --- a/regr-tests/test8-web/makefile +++ b/regr-tests/test8-web/makefile @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/regr-tests/test8-web/tc.uri b/regr-tests/test8-web/tc.uri index e7fc2bc..72242f4 100644 --- a/regr-tests/test8-web/tc.uri +++ b/regr-tests/test8-web/tc.uri @@ -1 +1 @@ -ws://clc1.trackio.ch:7000 +ws://localhost:7000 diff --git a/regr-tests/test8-web/test.sh b/regr-tests/test8-web/test.sh index b5ece18..2630d3e 100755 --- a/regr-tests/test8-web/test.sh +++ b/regr-tests/test8-web/test.sh @@ -1,7 +1,7 @@ #!/bin/bash # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -70,6 +70,53 @@ rm web/toobig.gz echo "---- Testing Broken HTTP Requests" +function ncit () { + # $1 -> allow empty responses + # $2 -> reqlist entry + local REQ="${2%%~*}" + local REF="${2##*~}" + local resp="`printf "$REQ" | nc -N 127.0.0.1 8080`" + if [ "$REF" == "DONTCARE" ]; then + return 0 + fi + if [ "$resp" == "" ] && [ "$REF" != "ref.empty" ]; then + echo "[INFO] empty response to $REQ -> expected $REF" && $1 + else + diff <(echo -n "$resp") <( echo -n "`cat $REF`" ) \ + || (echo "[FAILED] $REQ -> $REF" && false) + fi +} + +export -f ncit # make function available to GNU parallel + +# - Invalid HTTP headers + +REQLIST=( +"GET / HTTP/1.1\r\n \r\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~DONTCARE" +"GET\0 HTTP/1.1\n\r\n\r\n\r\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~DONTCARE" +"SCHMUTZ SCHMUTZ SCHMUTZ\rSCHMUTZ\nSCHMUTZ\r\n~~~~~~~~~~~~~~~~~~~~DONTCARE" +"SCHMUTZ SCHMUTZ SCHMUTZ\r\n\r\nSCHMUTZ\nSCHMUTZ~~~~~~~~~~~~~~~~~~DONTCARE" +"\r\n\r\nSCHMUTZ SCHMUTZ SCHMUTZ\r\n\r\nSCHMUTZ\nSCHMUTZ~~~~~~~~~~DONTCARE" +"\r\n\r\nSCHMUTZ\0SCHMUTZ SCHMUTZ\r\0\n\r\nSCHMUTZ\nSCHMUTZ~~~~~~~DONTCARE" +"\\//\/\../\\/..//\/\/./\.\~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~DONTCARE" +) + +NREQ=${#REQLIST[@]} +ROUNDS=500 + +for ((n=0;n<$ROUNDS;n++)); do + RND=$((RANDOM%NREQ)) + # echo "${REQLIST[$RND]}" + ncit false "${REQLIST[$RND]}" +done + +# Flush any remaining read buffer in station +for i in {1..3}; do + ncit false "GET /a HTTP/1.1\r\nHost: localhost:8080\r\nAccept: */*\r\n\r\n~~~DONTCARE" +done + +# - Valid HTTP headers + REQLIST=( "GET /a HTTP/1.1\r\nHost: localhost:8080\r\nAccept: */*\r\n\r\n~~~ref.a" "GET / HTTP/1.1\r\nAuthorization: xxxxxxxxxxxxxxxxxx\r\n\r\n~~~~~~ref.index.html" @@ -79,44 +126,22 @@ REQLIST=( "POST SCHMUTZ HTPP/1.1\r\n\r\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ref.400" "POST_/SCHMUTZ HTTP/1.1\r\n\r\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ref.400" "POST SCHMUTZ HTTP/1.1\r\n\r\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ref.400" -"GET / HTTP//1.1\r\n\r\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ref.400" -"GET / HTTP/1.1 \r\n\r\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ref.400" -"GET /\n HTTP/1.1\r\n\r\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ref.400" -"GET /\n\r HTTP/1.1\r\n\r\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ref.400" "GET /not_existing_file HTTP/1.1\r\n\r\n~~~~~~~~~~~~~~~~~~~~~~~~~~ref.404" "POST /version HTTP/1.1\r\n\r\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ref.405" "POP /version HTTP/1.1\r\n\r\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ref.405" "VERYLONGMETHOD1_@!#_!@# /version HTTP/1.1\r\n\r\n~~~~~~~~~~~~~~~~ref.405" -"GET / HTTP/1.1\r\n \r\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ref.empty" -"GET / HTTP/1.1\n\r\n\r\n\r\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ref.empty" -"GET\0 HTTP/1.1\n\r\n\r\n\r\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ref.empty" -"SCHMUTZ SCHMUTZ SCHMUTZ\rSCHMUTZ\nSCHMUTZ\r\n~~~~~~~~~~~~~~~~~~~~ref.empty" -"SCHMUTZ SCHMUTZ SCHMUTZ\r\n\r\nSCHMUTZ\nSCHMUTZ~~~~~~~~~~~~~~~~~~ref.empty" -"\r\n\r\nSCHMUTZ SCHMUTZ SCHMUTZ\r\n\r\nSCHMUTZ\nSCHMUTZ~~~~~~~~~~ref.empty" -"\r\n\r\nSCHMUTZ\0SCHMUTZ SCHMUTZ\r\0\n\r\nSCHMUTZ\nSCHMUTZ~~~~~~~ref.empty" -"\\//\/\../\\/..//\/\/./\.\~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ref.empty" +"GET / HTTP//1.1\r\n\r\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ref.400" +"GET / HTTP/1.1 \r\n\r\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ref.400" +"GET /\n HTTP/1.1\r\n\r\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ref.400" +"GET /\n\r HTTP/1.1\r\n\r\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ref.400" ) NREQ=${#REQLIST[@]} -ROUNDS=1500 - -function ncit () { - # $1 -> allow empty responses - local REQ="${2%%~*}" - local REF="${2##*~}" - local resp="`printf "$REQ" | nc -N 127.0.0.1 8080`" - if [ "$resp" == "" ] && [ "$REF" != "ref.empty" ]; then - echo "[WRN] Unexpected empty response to $REQ -> expected $REF" && $1 - else - diff <(echo -n "$resp") <( echo -n "`cat $REF`" ) \ - || (echo "[FAILED] $REQ -> $REF" && false) - fi -} - -export -f ncit # make function available to GNU parallel +ROUNDS=500 for ((n=0;n<$ROUNDS;n++)); do RND=$((RANDOM%NREQ)) + # echo "${REQLIST[$RND]}" ncit false "${REQLIST[$RND]}" done diff --git a/regr-tests/testlib.sh b/regr-tests/testlib.sh index c4e2723..158d1e7 100644 --- a/regr-tests/testlib.sh +++ b/regr-tests/testlib.sh @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: diff --git a/setup.gmk b/setup.gmk index a123556..d7c4363 100644 --- a/setup.gmk +++ b/setup.gmk @@ -1,5 +1,5 @@ # --- Revised 3-Clause BSD License --- -# Copyright Semtech Corporation 2020. All rights reserved. +# Copyright Semtech Corporation 2022. All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: @@ -108,10 +108,6 @@ SD.default = src-linux SD = $(or ${SD.${platform}}, ${SD.default}) -UTILS.linux = mtuns - -UTILS = $(or ${UTILS.${platform}}, ${UTILS.default}) - DEPS.default = mbedtls lgw DEPS.linuxpico = mbedtls smtcpico DEPS.linuxV2 = mbedtls lgw2 diff --git a/src-linux/cmdfifo.c b/src-linux/cmdfifo.c index 69609bf..e2f360f 100644 --- a/src-linux/cmdfifo.c +++ b/src-linux/cmdfifo.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -97,7 +97,7 @@ static void fifo_read(aio_t* _aio) { if( sendbuf.buf != NULL ) { memcpy(sendbuf.buf, cmdline, i); sendbuf.pos = i; - LOG(INFO, "CMD sent: %.40s", cmdline); + LOG(INFO, "CMD sent: %.40s%s", cmdline, i>40?"..":""); (*TC->s2ctx.sendText)(&TC->s2ctx, &sendbuf); } else { err = "Not enough WS space to sent command"; @@ -105,9 +105,9 @@ static void fifo_read(aio_t* _aio) { } else { err = "Command dropped - not connected right now"; } - if( err ) - LOG(ERROR,"%s: %.20s", err, cmdline); - + if( err ) { + LOG(ERROR,"%s: %.20s%s", err, cmdline, i>20?"..":""); + } fill = n -= i+1; memcpy(cmdline, cmdline+i+1, n); i = 0; diff --git a/src-linux/commands.c b/src-linux/commands.c index 028a27f..9346ae8 100644 --- a/src-linux/commands.c +++ b/src-linux/commands.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src-linux/gps.c b/src-linux/gps.c index 1f2179b..9371103 100644 --- a/src-linux/gps.c +++ b/src-linux/gps.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -53,6 +53,9 @@ int sys_enableGPS (str_t _device) { #include "s2conf.h" +// Special value to mark absent NMEA float/int field - e.g. $GPGGA,170801.00,,,,,0,00,99.99,,,,,,*69 +#define NILFIELD 0x423a0a60 + #if defined(CFG_ubx) // We don't need UBX to operate station - we get time from server // under the assumption both station and server are synced to a PPS. @@ -64,9 +67,9 @@ int sys_enableGPS (str_t _device) { static u1_t UBX_EN_NAVTIMEGPS[] = { UBX_SYN1, UBX_SYN2, 0x06, 0x01, // class/ID - 0x08, 0x00, // payload length - 0x01, 0x20, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, // Enable NAV-TIMEGPS output on serial - 0x32, 0x94 // checksum + 0x03, 0x00, // payload length + 0x01, 0x20, 0x01, // Enable NAV-TIMEGPS messages on current port (serial) with 1s rate + 0x2C, 0x83 // checksum }; #endif // defined(CFG_ubx) @@ -116,6 +119,7 @@ static int nmea_cksum ( u1_t* data, int len) { int s = (rt_hexDigit(data[i+1]) << 4) | rt_hexDigit(data[i+2]); if( s!=v) LOG(MOD_GPS|ERROR,"NMEA checksum error: %02X vs %02X", s, v); + data[i+1] = data[i+2] = 0; // used for missing fields detection return s==v; } v ^= data[i]; @@ -124,13 +128,26 @@ static int nmea_cksum ( u1_t* data, int len) { } +// Parse a set of NMEA fields as string values. +// Return zero terinated pointers. Note, field terminators (, / * ) are +// overwritten with \0. +// IN: +// pp - current read pointer into NMEA sentecne - at the start of a field +// cnt - number fields to parse +// args - array of pointers to found field starts (zero terminated strings) +// RETURN: +// 0 - parsing failed - not enough fields +// 1 - parsing ok - field starts in args[0:cnt] +// OUT: +// pp - advanced read pointer - stops after cnt-th field (after , or *) +// args[..] - pointers to found field starts static int nmea_str (char** pp, int cnt, char** args) { char* p = *pp; int c, i = 0; - c = p[0]; while( i < cnt ) { - if( c == '*' ) - return 0; + if( p[0] == '\0' ) { + return 0; // field missing + } args[i] = p; while( (c=p[0]) != ',' && c != '*' ) p++; @@ -144,8 +161,13 @@ static int nmea_str (char** pp, int cnt, char** args) { static int nmea_decimal(char** pp, sL_t* pv) { char* p = *pp; - if( p[0] == '*' ) - return 0; + if( p[0] == '\0' ) { + return 0; // field missing + } + if( p[0] == '*' || p[0] == ',' ) { + pv[0] = NILFIELD; + return 1; + } int sign = 0; if( *p == '-' ) { p++; @@ -164,8 +186,13 @@ static int nmea_decimal(char** pp, sL_t* pv) { static int nmea_float(char** pp, double* pv) { char* p = *pp; - if( p[0] == '*' ) - return 0; + if( p[0] == '\0' ) { + return 0; // field missing + } + if( p[0] == '*' || p[0] == ',' ) { + pv[0] = NILFIELD; + return 1; + } int sign = 0; if( *p == '-' ) { p++; @@ -221,11 +248,12 @@ str_t GPSEV_MOVE = "move"; str_t GPSEV_FIX = "fix"; str_t GPSEV_NOFIX = "nofix"; -static int send_gpsev_fix(str_t gpsev, float lat, float lon, float alt, float dilution, int satellites, int quality, float from_lat, float from_lon) { +static int send_gpsev_fix(str_t gpsev, float lat, float lon, float alt, + float dilution, int satellites, int quality, float from_lat, float from_lon) { assert(gpsev == GPSEV_MOVE || gpsev == GPSEV_FIX || gpsev == GPSEV_NOFIX); ujbuf_t sendbuf = (*TC->s2ctx.getSendbuf)(&TC->s2ctx, MIN_UPJSON_SIZE); if( sendbuf.buf == NULL ) { - LOG(MOD_S2E|ERROR, "Failed to send gps event, no buffer space"); + LOG(MOD_S2E|ERROR, "Failed to send GPS event. Either no TC connection or insufficient IO buffer space."); return 0; } uj_encOpen(&sendbuf, '{'); @@ -249,14 +277,14 @@ static int send_gpsev_fix(str_t gpsev, float lat, float lon, float alt, float di LOG(MOD_GPS|INFO, "GPS fix: %.7f,%.7f alt=%.1f dilution=%f satellites=%d quality=%d", lat, lon, alt, dilution, satellites, quality); return send_alarm("{\"msgtype\":\"alarm\"," - "\"text\":\"GPS fix: %.7f,%.7f alt=%.1f dilution=%f satellites=%d quality=%d\"}", - lat, lon, alt, dilution, satellites, quality); + "\"text\":\"GPS fix: %.7f,%.7f alt=%.1f dilution=%f satellites=%d quality=%d\"}", + lat, lon, alt, dilution, satellites, quality); } else { LOG(MOD_GPS|INFO, "GPS move %.7f,%.7f => %.7f,%.7f (alt=%.1f dilution=%f satellites=%d quality=%d)", from_lat, from_lon, lat, lon, alt, dilution, satellites, quality); return send_alarm("{\"msgtype\":\"alarm\"," - "\"text\":\"GPS move %.7f,%.7f => %.7f,%.7f (alt=%.1f dilution=%f satellites=%d quality=%d)\"}", - from_lat, from_lon, lat,lon, alt, dilution, satellites, quality); + "\"text\":\"GPS move %.7f,%.7f => %.7f,%.7f (alt=%.1f dilution=%f satellites=%d quality=%d)\"}", + from_lat, from_lon, lat, lon, alt, dilution, satellites, quality); } } @@ -282,17 +310,17 @@ static int send_gpsev_nofix(ustime_t since) { LOG(MOD_GPS|INFO, "GPS nofix: since %~T", since); return send_alarm("{\"msgtype\":\"alarm\"," - "\"text\":\"No GPS fix since %~T\"}", since); + "\"text\":\"No GPS fix since %~T\"}", since); } static float nmea_p2dec(float lat, char d) { - s4_t dd = (s4_t)(lat/100); - float ss = lat - dd * 100; - float dec = (ss/60.0 + dd); - return (d == 'S' || d == 'W') ? (-1 * dec) : dec; + s4_t dd = (s4_t)(lat/100); + float ss = lat - dd * 100; + float dec = (ss/60.0 + dd); + return (d == 'S' || d == 'W') ? (-1 * dec) : dec; } @@ -315,7 +343,10 @@ static void nmea_gga (char* p) { LOG(MOD_GPS|ERROR, "Failed to parse GPS GGA sentence: (len=%d) %.*s", len, len, pp); return; } - + if( lat == NILFIELD || lon == NILFIELD ) { + LOG(MOD_GPS|WARNING, "GGA sentence without a fix - bad GPS signal?"); + return; + } lat = nmea_p2dec(lat, latD[0]); lon = nmea_p2dec(lon, lonD[0]); LOG(MOD_GPS|XDEBUG, "nmea_gga: lat %f, lon %f", lat, lon); @@ -341,7 +372,7 @@ static void nmea_gga (char* p) { if( fix < 0 ) { ustime_t thres = time_fixchange + (1< thres && - send_gpsev_nofix(time_fixchange-now)) { + send_gpsev_nofix(now-time_fixchange)) { last_reported_fix = fix; nofix_backoff = max(nofix_backoff+1, 16); } @@ -371,14 +402,8 @@ static void nmea_gga (char* p) { last_quality = quality; if( report_move && - send_gpsev_fix(GPSEV_MOVE, lat, lon, alt, dilution, satellites, quality, from_lon, from_lon)) { - //send_alarm("{\"msgtype\":\"alarm\"," - //"\"text\":\"GPS move %.7f,%.7f => %.7f,%.7f (alt=%.1f dilution=%f satellites=%d quality=%d)\"}", - // from_lat, from_lon, orig_lat, orig_lon, alt, dilution, satellites, quality) ) { + send_gpsev_fix(GPSEV_MOVE, lat, lon, alt, dilution, satellites, quality, from_lat, from_lon)) { report_move = 0; - //LOG(MOD_GPS|INFO, "GPS move %.7f,%.7f => %.7f,%.7f (alt=%.1f dilution=%f satellites=%d quality=%d)", - // from_lat, from_lon, orig_lat, orig_lon, alt, dilution, satellites, quality); - } } @@ -413,7 +438,7 @@ static void gps_read(aio_t* _aio) { for( int i=0; i n ) break; // need more data to read header @@ -438,23 +464,28 @@ static void gps_read(aio_t* _aio) { break; u2_t cksum = rt_rlsbf2(&gpsline[i+6+ubxlen]); u2_t fltch = fletcher8(&gpsline[i+2], ubxlen+4); - LOG(MOD_GPS|DEBUG, "UBX cksum=%04X vs found=%04X", cksum, fltch); if( cksum != fltch ) { + LOG(MOD_GPS|XDEBUG, "UBX cksum=%04X vs found=%04X", cksum, fltch); done = i+1; break; } done = i+8+ubxlen; + // NAV-TIMEGPS if( gpsline[i+2] == 0x01 && gpsline[i+3] == 0x20 && ubxlen == 16 ) { - u4_t tow = rt_rlsbf4(&gpsline[i+6]); // GPS time of week in ms - u4_t tow_ns = rt_rlsbf4(&gpsline[i+6+4]); - u2_t week = rt_rlsbf2(&gpsline[i+6+4+2]); - u1_t leapsecs = gpsline[i+6+4+2+0]; - u1_t status = gpsline[i+6+4+2+1]; - u4_t tacc = rt_rlsbf4(&gpsline[i+6+4+2+2]); - LOG(MOD_GPS|DEBUG, "NAV-TIMEGPS tow(ms)=%d.%06d week=%d leapsecs=%d status=%d tacc=%d", - tow, tow_ns, week, leapsecs, status, tacc); + u4_t itow = rt_rlsbf4(&gpsline[i+6]); // GPS time of week in ms + s4_t ftow = rt_rlsbf4(&gpsline[i+6+4]); // +/- 500000 ns + u2_t week = rt_rlsbf2(&gpsline[i+6+4+4]); + u1_t leapsecs = gpsline[i+6+4+4+2]; + u1_t valid = gpsline[i+6+4+4+2+1]; + u4_t tacc = rt_rlsbf4(&gpsline[i+6+4+4+2+1+1]); + if( ftow < 0 ) { + itow -= 1; + ftow += 1000000; + } + LOG(MOD_GPS|XDEBUG, "NAV-TIMEGPS tow(ms)=%d.%06d week=%d leapsecs=%d valid=0x%x tacc(ns)=%d", + itow, ftow, week, leapsecs, valid, tacc); } else { - LOG(MOD_GPS|WARNING, "Unknown UBX frame: %H", 8+ubxlen, &gpsline[i]); + LOG(MOD_GPS|XDEBUG, "Unknown UBX frame: %H", 8+ubxlen, &gpsline[i]); } break; } @@ -589,7 +620,7 @@ int sys_enableGPS (str_t _device) { return 1; // no GPS device configured device = _device; baud = 9600; - ubx = 0; + ubx = 1; rt_iniTimer(&reopen_tmr, reopen_timeout); if( !gps_reopen() ) { @@ -621,4 +652,3 @@ int sys_enableGPS (str_t _device) { } #endif - diff --git a/src-linux/leds.c b/src-linux/leds.c index 9690d8b..29d887c 100644 --- a/src-linux/leds.c +++ b/src-linux/leds.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src-linux/ral_master.c b/src-linux/ral_master.c index 2860fe7..3fa397b 100644 --- a/src-linux/ral_master.c +++ b/src-linux/ral_master.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -463,6 +463,7 @@ int ral_tx (txjob_t* txjob, s2ctx_t* s2ctx, int nocca) { req.xtime = txjob->xtime; req.freq = txjob->freq; req.txpow = txjob->txpow; + req.addcrc = txjob->addcrc; req.txlen = txjob->len; memcpy(req.txdata, &s2ctx->txq.txdata[txjob->off], txjob->len); if( !write_slave_pipe(slave, &req, sizeof(req)) ) @@ -644,6 +645,7 @@ void ral_stop () { struct ral_timesync_req req = { .cmd = RAL_CMD_STOP, .rctx = 0 }; for( int slaveIdx=0; slaveIdx < n_slaves; slaveIdx++ ) { slave_t* slave = &slaves[slaveIdx]; + rt_clrTimer(&slave->tsync); write_slave_pipe(slave, &req, sizeof(req)); } } diff --git a/src-linux/ral_slave.c b/src-linux/ral_slave.c index fca12af..55ffc96 100644 --- a/src-linux/ral_slave.c +++ b/src-linux/ral_slave.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -41,6 +41,9 @@ #include "sx130xconf.h" #include "lgw/loragw_hal.h" +#if !defined(LGW_PKT_FIFO_SIZE) +#define LGW_PKT_FIFO_SIZE 16 +#endif static u1_t pps_en; static sL_t last_xtime; @@ -72,6 +75,27 @@ static void pipe_write_data (void* data, int len) { } } +static void log_rawpkt(u1_t level, str_t msg, struct lgw_pkt_rx_s * pkt_rx) { + LOG(MOD_RAL|level, "%s[CRC %s] %^.3F %.2f/%.1f %R (mod=%d/dr=%d/bw=%d) xtick=%08x (%u) %d bytes: %64H", + msg, + pkt_rx->status == STAT_CRC_OK ? "OK" : "FAIL", + pkt_rx->freq_hz, + pkt_rx->snr, +#if defined(CFG_sx1302) + pkt_rx->rssis, +#else + pkt_rx->rssi, +#endif + ral_lgw2rps(pkt_rx), + pkt_rx->modulation, + pkt_rx->datarate, + pkt_rx->bandwidth, + pkt_rx->count_us, + pkt_rx->count_us, + pkt_rx->size, + pkt_rx->size, pkt_rx->payload + ); +} static void rx_polling (tmr_t* tmr) { int n; @@ -83,14 +107,15 @@ static void rx_polling (tmr_t* tmr) { for( int i=0; istatus != STAT_CRC_OK ) { - LOG(MOD_RAL|DEBUG, "Dropped frame with %s CRC (0x%X)", - p->status == STAT_CRC_BAD ? "bad" : p->status == STAT_NO_CRC ? "no" : "undefined", p->status); + if( log_shallLog(MOD_RAL|DEBUG) ) { + log_rawpkt(DEBUG, "", p); + } continue; // silently ignore bad CRC } if( p->size > MAX_RXFRAME_LEN ) { // This should not happen since caller provides // space for max frame length - 255 bytes - LOG(MOD_RAL|ERROR, "Frame size (%d) exceeds offered buffer (%d)", p->size, MAX_RXFRAME_LEN); + log_rawpkt(ERROR, "Dropped RX frame - frame size too large: ", p); continue; } struct ral_rx_resp resp; @@ -100,10 +125,19 @@ static void rx_polling (tmr_t* tmr) { resp.xtime = ts_xticks2xtime(p->count_us, last_xtime); resp.rps = ral_lgw2rps(p); resp.freq = p->freq_hz; - resp.rssi = (u1_t)(p->rssi * -1); - resp.snr = (s1_t)(p->snr * 8); +#if defined(CFG_sx1302) + resp.rssi = (u1_t)-p->rssis; +#else + resp.rssi = (u1_t)-p->rssi; +#endif + resp.snr = (s1_t)(p->snr * 4); resp.rxlen = p->size; memcpy(resp.rxdata, p->payload, p->size); + + if( log_shallLog(MOD_RAL|XDEBUG) ) { + log_rawpkt(XDEBUG, "", p); + } + pipe_write_data(&resp, sizeof(resp)); } } @@ -143,7 +177,11 @@ static void pipe_read (aio_t* aio) { off += sizeof(struct ral_txstatus_req); struct ral_response* resp = (struct ral_response*)req; u1_t ret=TXSTATUS_IDLE, status; +#if defined(CFG_sx1302) + int err = lgw_status(0, TX_STATUS, &status); +#else int err = lgw_status(TX_STATUS, &status); +#endif /**/ if (err != LGW_HAL_SUCCESS) { LOG(MOD_RAL|ERROR, "lgw_status failed"); } else if( status == TX_SCHEDULED ) { ret = TXSTATUS_SCHEDULED; } else if( status == TX_EMITTING ) { ret = TXSTATUS_EMITTING; } @@ -153,7 +191,11 @@ static void pipe_read (aio_t* aio) { } else if( n >= off + sizeof(struct ral_txabort_req) && req->cmd == RAL_CMD_TXABORT) { off += sizeof(struct ral_txabort_req); +#if defined(CFG_sx1302) + lgw_abort_tx(0); +#else lgw_abort_tx(); +#endif continue; } else if( n >= off + sizeof(struct ral_timesync_req) && req->cmd == RAL_CMD_TIMESYNC) { @@ -165,9 +207,15 @@ static void pipe_read (aio_t* aio) { off += sizeof(struct ral_tx_req); struct ral_tx_req* txreq = (struct ral_tx_req*)req; struct lgw_pkt_tx_s pkt_tx; + + pkt_tx.invert_pol = true; + pkt_tx.no_header = false; + if( (txreq->rps & RPS_BCN) ) { pkt_tx.tx_mode = ON_GPS; pkt_tx.preamble = 10; + pkt_tx.invert_pol = false; + pkt_tx.no_header = true; } else { pkt_tx.tx_mode = TIMESTAMPED; pkt_tx.preamble = 8; @@ -178,12 +226,14 @@ static void pipe_read (aio_t* aio) { pkt_tx.rf_chain = 0; pkt_tx.rf_power = (float)(txreq->txpow - txpowAdjust)/TXPOW_SCALE; pkt_tx.coderate = CR_LORA_4_5; - pkt_tx.invert_pol = true; - pkt_tx.no_crc = true; - pkt_tx.no_header = false; + pkt_tx.no_crc = !txreq->addcrc; pkt_tx.size = txreq->txlen; memcpy(pkt_tx.payload, txreq->txdata, txreq->txlen); +#if defined(CFG_sx1302) + int err = lgw_send(&pkt_tx); +#else int err = lgw_send(pkt_tx); +#endif if( region == 0 ) { continue; } @@ -227,6 +277,8 @@ static void pipe_read (aio_t* aio) { } else if( n >= off + sizeof(struct ral_stop_req) && req->cmd == RAL_CMD_STOP) { off += sizeof(struct ral_stop_req); + last_xtime = 0; + rt_clrTimer(&rxpoll_tmr); lgw_stop(); continue; } diff --git a/src-linux/ralsub.h b/src-linux/ralsub.h index 20f9f02..b6b0897 100644 --- a/src-linux/ralsub.h +++ b/src-linux/ralsub.h @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -85,8 +85,9 @@ struct ral_tx_req { sL_t rctx; u1_t cmd; u1_t txlen; - u1_t txpow; + s2_t txpow; rps_t rps; + u1_t addcrc; u4_t freq; sL_t xtime; u1_t txdata[MAX_TXFRAME_LEN]; diff --git a/src-linux/rmtsh.c b/src-linux/rmtsh.c index d4567e3..53e3130 100644 --- a/src-linux/rmtsh.c +++ b/src-linux/rmtsh.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src-linux/station_main.c b/src-linux/station_main.c index a4ecc8a..a846fd8 100644 --- a/src-linux/station_main.c +++ b/src-linux/station_main.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src-linux/sys_linux.c b/src-linux/sys_linux.c index 5b637c9..2bbb7e5 100644 --- a/src-linux/sys_linux.c +++ b/src-linux/sys_linux.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -51,6 +51,8 @@ #include "fs.h" #include "selftests.h" +#include "mbedtls/version.h" + extern char* makeFilepath (const char* prefix, const char* suffix, char** pCachedFile, int isReadable); // sys.c extern int writeFile (str_t file, const char* data, int datalen); extern dbuf_t readFile (str_t file, int complain); @@ -119,23 +121,33 @@ static void handle_signal (int signum) { static int updateDirSetting (str_t path, str_t source, str_t* pdir, str_t* psrc) { int l = strlen(path); - char* p = rt_mallocN(char, l+3); - if( l == 0 ) { - strcpy(p, "./"); + char* p = rt_mallocN(char, l+5); // more space for optional "./" and/or "/" + "\0" + if( path[0] ) { + strcpy(p,path); } else { - struct stat st; - if( stat(path, &st) == -1 ) { - fprintf(stderr, "%s - Cannot access directory '%s': %s\n", source, path, strerror(errno)); - return 0; - } - if( !S_ISDIR(st.st_mode) ) { - fprintf(stderr, "%s - Not a directory: %s\n", source, path); - return 0; - } - strcpy(p, path); - if( l>0 && p[l-1] != '/' ) - p[l] = '/'; + strcpy(p,"./"); + l = 2; + } + if( p[l-1] != '/' ) { + p[l++] = '/'; + } + if( p[0] != '/' && (p[0] != '.' || p[1] != '/') ) { + memmove(p+2, p, l+1); + p[0] = '.'; + p[1] = '/'; + } + struct stat st; + if( stat(p, &st) == -1 ) { + fprintf(stderr, "%s - Cannot access directory '%s': %s\n", source, p, strerror(errno)); + goto err; + } + if( !S_ISDIR(st.st_mode) ) { + fprintf(stderr, "%s - Not a directory: %s\n", source, p); + err: + rt_free(p); + return 0; } + rt_free((void*)*pdir); rt_free((void*)*psrc); *pdir = p; @@ -298,10 +310,26 @@ int sys_findPids (str_t device, u4_t* pids, int n_pids) { } -str_t sys_radioDevice (str_t device) { +str_t sys_radioDevice (str_t device, u1_t* comtype) { str_t f = device==NULL ? radioDevice : device; if( f == NULL ) f = RADIODEV; + // check for comtype prefix + if( comtype ) + *comtype = COMTYPE_SPI; + char *colon = index(f, ':'); + if( colon ) { + if( strncmp(f, "spi:", 4) == 0 ) { + if( comtype ) + *comtype = COMTYPE_SPI; + } else if( strncmp(f, "usb:", 4) == 0 ) { + if( comtype ) + *comtype = COMTYPE_USB; + } else { + LOG(MOD_SYS|ERROR, "Unknown device comtype '%.*s' (using SPI)", colon-f, f); + } + f = colon + 1; + } // Caller must free result return sys_makeFilepath(f, 0); } @@ -366,6 +394,7 @@ void sys_ini () { logfile.path==NULL ? "stderr" : logfile.path, logfile.size, logfile.rotate); LOG(MOD_SYS|INFO, "Station Ver : %s", CFG_version " " CFG_bdate); LOG(MOD_SYS|INFO, "Package Ver : %s", sys_version()); + LOG(MOD_SYS|INFO, "mbedTLS Ver : %s", MBEDTLS_VERSION_STRING); LOG(MOD_SYS|INFO, "proto EUI : %:E\t(%s)", protoEUI, protoEuiSrc); LOG(MOD_SYS|INFO, "prefix EUI : %:E\t(%s)", prefixEUI, prefixEuiSrc); LOG(MOD_SYS|INFO, "Station EUI : %:E", sys_eui()); @@ -527,7 +556,7 @@ int sys_execCommand (ustime_t max_wait, str_t* argv) { if( max_wait!=0 || (pid2 = fork()) == 0 ) { if( access(argv[0], X_OK) != 0 ) { // Not an executable file - str_t* argv2 = rt_mallocN(str_t, argc+3); + str_t* argv2 = rt_mallocN(str_t, argc+4); memcpy(&argv2[3], &argv[0], sizeof(argv[0])*(argc+1)); // also copy trailing NULL if( access(argv[0], F_OK) == -1 ) { // Not even a file - assume shell statements @@ -544,13 +573,16 @@ int sys_execCommand (ustime_t max_wait, str_t* argv) { } for( int i=0; argv[i]; i++ ) LOG(MOD_SYS|DEBUG, "%s argv[%d]: <%s>\n", i==0?"execvp":" ", i, argv[i]); + log_flushIO(); if( execvp(argv[0], (char*const*)argv) == -1 ) { LOG(MOD_SYS|ERROR, "%s: Failed to exec: %s", argv[0], strerror(errno)); + log_flushIO(); exit(9); } } else if( pid2 < 0 ) { LOG(MOD_SYS|ERROR, "%s: Fork(2) failed: %s", argv[0], strerror(errno)); + log_flushIO(); exit(8); } exit(0); @@ -965,9 +997,9 @@ static int parse_opt (int key, char* arg, struct argp_state* state) { return 0; } case 'v': { - fputs("Station: " CFG_version " " CFG_bdate "\n", stderr); + fputs("Station: " CFG_version " " CFG_bdate "\n", stdout); readFileAsString("version", ".txt", &versionTxt); - fprintf(stderr, "Package: %s\n", versionTxt); + fprintf(stdout, "Package: %s\n", versionTxt); exit(0); } case ARGP_KEY_END: { diff --git a/src-linux/sys_linux.h b/src-linux/sys_linux.h index 002a9b9..048cf36 100644 --- a/src-linux/sys_linux.h +++ b/src-linux/sys_linux.h @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src-linux/sys_log.c b/src-linux/sys_log.c index cce7a35..33aa2e6 100644 --- a/src-linux/sys_log.c +++ b/src-linux/sys_log.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src-linux/web_linux.c b/src-linux/web_linux.c index 6eef4cb..76cd8dc 100644 --- a/src-linux/web_linux.c +++ b/src-linux/web_linux.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/aio.c b/src/aio.c index 90f24e9..f6ddad7 100644 --- a/src/aio.c +++ b/src/aio.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/argp.c b/src/argp.c index fca18a9..f4719c2 100644 --- a/src/argp.c +++ b/src/argp.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/argp2.h b/src/argp2.h index 070ffec..4205b04 100644 --- a/src/argp2.h +++ b/src/argp2.h @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/crc32.c b/src/crc32.c index 33bf398..e21fbaa 100644 --- a/src/crc32.c +++ b/src/crc32.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/cups.c b/src/cups.c index e3d6079..b655826 100644 --- a/src/cups.c +++ b/src/cups.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -245,6 +245,7 @@ static void cups_update_info (conn_t* _conn, int ev) { uj_encClose(&b, ']'); uj_encClose(&b, '}'); http_setContentLength(b.buf, b.pos-bodybeg); + LOG(MOD_CUP|DEBUG, "CUPS Request: %.*s", b.pos-bodybeg, b.buf+bodybeg); http_request(&cups->hc, &b); return; } @@ -258,7 +259,7 @@ static void cups_update_info (conn_t* _conn, int ev) { int status = http_getStatus(&cups->hc); if( status != 200 ) { dbuf_t msg = http_statusText(&hdr); - LOG(VERBOSE, "Failed to retrieve TCURI from CUPS: (%d) %.*s", status, msg.bufsize, msg.buf); + LOG(MOD_CUP|VERBOSE, "Failed to retrieve TCURI from CUPS: (%d) %.*s", status, msg.bufsize, msg.buf); cups->cstate = CUPS_ERR_REJECTED; http_close(&cups->hc); return; @@ -270,14 +271,16 @@ static void cups_update_info (conn_t* _conn, int ev) { u1_t cupsuri_len = body.buf[0]; u1_t tcuri_len = body.buf[1+cupsuri_len]; body.pos = 2+cupsuri_len+tcuri_len; // after both URI segments - if( body.bufsize < 2 || 1+body.pos > body.bufsize ) // need one more byte for \0 + if( body.bufsize < 2 || 1+body.pos > body.bufsize ) { // need one more byte for \0 + LOG(MOD_CUP|ERROR, "Malformed CUPS response: URI segments lengths (%u) exceed available data (%u)", body.pos, body.bufsize); goto proto_err; + } sys_resetConfigUpdate(); if( cupsuri_len ) { str_t uri = (str_t)body.buf+1; body.buf[1+cupsuri_len] = 0; sys_saveUri(SYS_CRED_CUPS, uri); - LOG(MOD_CUP|INFO, "CUPS URI updated: %s", uri); + LOG(MOD_CUP|INFO, "[Segment] CUPS URI: %s", uri); cups->uflags |= UPDATE_FLAG(CUPS_URI); } if( tcuri_len ) { @@ -285,7 +288,7 @@ static void cups_update_info (conn_t* _conn, int ev) { char save = uri[tcuri_len]; uri[tcuri_len] = 0; sys_saveUri(SYS_CRED_TC, uri); - LOG(MOD_CUP|INFO, "TC URI updated: %s", uri); + LOG(MOD_CUP|INFO, "[Segment] TC URI: %s", uri); uri[tcuri_len] = save; cups->uflags |= UPDATE_FLAG(TC_URI); } @@ -333,14 +336,14 @@ static void cups_update_info (conn_t* _conn, int ev) { if( cstate == CUPS_FEED_CUPS_CRED ) { sys_credStart(SYS_CRED_CUPS, segm_len); cups->uflags |= UPDATE_FLAG(CUPS_CRED); - LOG(MOD_CUP|INFO, "CUPS Credentials segment (%d bytes)", segm_len); + LOG(MOD_CUP|INFO, "[Segment] CUPS Credentials (%d bytes)", segm_len); } else if( cstate == CUPS_FEED_TC_CRED ) { sys_credStart(SYS_CRED_TC, segm_len); cups->uflags |= UPDATE_FLAG(TC_CRED); - LOG(MOD_CUP|INFO, "TC Credentials segment (%d bytes)", segm_len); + LOG(MOD_CUP|INFO, "[Segment] TC Credentials (%d bytes)", segm_len); } else if( cstate == CUPS_FEED_SIGNATURE ) { - LOG(MOD_CUP|INFO, "Signature segment (%d bytes)", segm_len); + LOG(MOD_CUP|INFO, "[Segment] FW Signature (%d bytes)", segm_len); rt_free(cups->sig); if( segm_len < 8 || segm_len > sizeof(cups->sig->signature) + SIGCRC_LEN ) { LOG(MOD_CUP|ERROR, "Illegal signature segment length (must be 8-%d bytes): %d", sizeof(cups->sig->signature) + SIGCRC_LEN, segm_len); @@ -351,7 +354,7 @@ static void cups_update_info (conn_t* _conn, int ev) { assert(cstate == CUPS_FEED_UPDATE); sys_commitConfigUpdate(); sys_updateStart(segm_len); - LOG(MOD_CUP|INFO, "Update segment (%d bytes)", segm_len); + LOG(MOD_CUP|INFO, "[Segment] FW Update (%d bytes)", segm_len); } } } @@ -360,11 +363,11 @@ static void cups_update_info (conn_t* _conn, int ev) { // Segment finished if( cstate == CUPS_FEED_CUPS_CRED ) { sys_credComplete(SYS_CRED_CUPS, cups->segm_len); - LOG(MOD_CUP|INFO, "CUPS credentials updated (%d bytes)", cups->segm_len); + LOG(MOD_CUP|INFO, "[Segment] CUPS Credentials update completed (%d bytes)", cups->segm_len); } else if( cstate == CUPS_FEED_TC_CRED ) { sys_credComplete(SYS_CRED_TC, cups->segm_len); - LOG(MOD_CUP|INFO, "TC credentials updated (%d bytes)", cups->segm_len); + LOG(MOD_CUP|INFO, "[Segment] TC Credentials update completed (%d bytes)", cups->segm_len); } else if( cstate == CUPS_FEED_SIGNATURE ) { cups->uflags |= UPDATE_FLAG(SIGNATURE); cups->sig->len = cups->segm_len - SIGCRC_LEN; @@ -374,9 +377,9 @@ static void cups_update_info (conn_t* _conn, int ev) { else { // cstate == CUPS_FEED_UPDATE if( sys_updateCommit(cups->segm_len) ) { cups->uflags |= UPDATE_FLAG(UPDATE); - LOG(MOD_CUP|INFO, "Update received (%d bytes)", cups->segm_len); + LOG(MOD_CUP|INFO, "[Segment] Update committed (%d bytes)", cups->segm_len); } else { - LOG(MOD_CUP|ERROR, "Update received (%d bytes) but failed to write (ignored)", cups->segm_len); + LOG(MOD_CUP|ERROR, "[Segment] Update received (%d bytes) but failed to write (ignored)", cups->segm_len); } } goto next_cstate; @@ -463,6 +466,7 @@ void cups_start (cups_t* cups) { } LOG(MOD_CUP|INFO, "Connecting to CUPS%s ... %s (try #%d)", sys_credset2str(cups_credset), cupsuri, cups_failCnt+1); + log_flushIO(); // Use HTTP buffer as temp place for host/port strings // Gets destroyed when reading response. char* hostname = (char*)cups->hc.c.rbuf; diff --git a/src/cups.h b/src/cups.h index 2b849e5..ab11439 100644 --- a/src/cups.h +++ b/src/cups.h @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/flashsim.c b/src/flashsim.c index 72b46ce..aa4fb21 100644 --- a/src/flashsim.c +++ b/src/flashsim.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/fs.c b/src/fs.c index 0d485dc..60e4fd0 100644 --- a/src/fs.c +++ b/src/fs.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -797,6 +797,13 @@ int fs_lseek (int fd, int offset, int whence) { } +void fs_sync () { +#if defined(CFG_linux) + sync(); +#endif // defined(CFG_linux) +} + + static int fs_validateRecord (fctx_t* fctx) { u4_t begtag = fctx_begtag(fctx); u2_t ino = FSTAG_ino(begtag); diff --git a/src/fs.h b/src/fs.h index 01a2a52..6149150 100644 --- a/src/fs.h +++ b/src/fs.h @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -41,16 +41,17 @@ void rdFlashN (u4_t faddr, u4_t* daddr, uint u4cnt); void wrFlash1 (u4_t faddr, u4_t data); void wrFlashN (u4_t faddr, u4_t* daddr, uint u4cnt, int keepData); -int fs_open (str_t filename, int mode, ...); -int fs_read (int fd, void* buf, int size); -int fs_write (int fd, const void* buf, int size); -int fs_close (int fd); -int fs_rename (str_t from, str_t to); -int fs_unlink (str_t from); -int fs_chdir (str_t dir); -int fs_access (str_t fn, int mode); -int fs_stat (str_t fn, struct stat* st); -int fs_lseek (int fd, int offset, int whence); +int fs_open (str_t filename, int mode, ...); +int fs_read (int fd, void* buf, int size); +int fs_write (int fd, const void* buf, int size); +int fs_close (int fd); +int fs_rename (str_t from, str_t to); +int fs_unlink (str_t from); +int fs_chdir (str_t dir); +int fs_access (str_t fn, int mode); +int fs_stat (str_t fn, struct stat* st); +int fs_lseek (int fd, int offset, int whence); +void fs_sync (); int fs_fnNormalize (const char* fn, char* wb, int maxsz); diff --git a/src/genkwcrcs.c b/src/genkwcrcs.c index 4b41f7e..c941f67 100644 --- a/src/genkwcrcs.c +++ b/src/genkwcrcs.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -73,7 +73,14 @@ int main (int argc, char** argv) { printf("#define UJ_UPDATE_CRC(crc,c) %s\n", 4+STR(UPDATE_CRC(crc,c))); printf("#define UJ_FINISH_CRC(crc) %s\n", 4+STR(FINISH_CRC(crc))); for( int i=0; i='0' && c<='9') || (c>='a' && c<='z') || (c>='A' && c<='Z') ? c : '_'; + } + ident[cj] = 0; + printf("#define J_%-20s ((ujcrc_t)(0x%08X))\n", ident, crcs[i]); } return 0; } diff --git a/src/http.h b/src/http.h index 83c4b1f..63e0d35 100644 --- a/src/http.h +++ b/src/http.h @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/httpd.h b/src/httpd.h index d871c85..abef60b 100644 --- a/src/httpd.h +++ b/src/httpd.h @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/kwcrc.h b/src/kwcrc.h index 02a6fd7..033281d 100644 --- a/src/kwcrc.h +++ b/src/kwcrc.h @@ -7,6 +7,7 @@ #define J_api ((ujcrc_t)(0x00617278)) #define J_arguments ((ujcrc_t)(0x5ACAD020)) #define J_AS923 ((ujcrc_t)(0xD653976B)) +#define J_AS923_1 ((ujcrc_t)(0x66169288)) #define J_AS923JP ((ujcrc_t)(0x6616F98E)) #define J_asap ((ujcrc_t)(0x61D4E603)) #define J_AU915 ((ujcrc_t)(0xD8599E68)) @@ -37,6 +38,7 @@ #define J_error ((ujcrc_t)(0x47A7EB1D)) #define J_EU433 ((ujcrc_t)(0xE0569061)) #define J_EU863 ((ujcrc_t)(0xE0529B68)) +#define J_EU868 ((ujcrc_t)(0xE0529B63)) #define J_euiprefix ((ujcrc_t)(0x9D5E0C96)) #define J_shell ((ujcrc_t)(0x767A1E0A)) #define J_cmd ((ujcrc_t)(0x0063716A)) @@ -116,6 +118,7 @@ #define J_upgrade ((ujcrc_t)(0xF49BF544)) #define J_uri ((ujcrc_t)(0x00757C6E)) #define J_US902 ((ujcrc_t)(0x061FA968)) +#define J_US915 ((ujcrc_t)(0x061FA86E)) #define J_user ((ujcrc_t)(0x75F0DE11)) #define J_version ((ujcrc_t)(0x00E51D6C)) #define J_web_port ((ujcrc_t)(0xA9963701)) diff --git a/src/kwlist.txt b/src/kwlist.txt index c12925f..7516d92 100644 --- a/src/kwlist.txt +++ b/src/kwlist.txt @@ -4,6 +4,7 @@ antenna_type api arguments AS923 +AS923-1 AS923JP asap AU915 @@ -34,6 +35,7 @@ enable error EU433 EU863 +EU868 euiprefix shell cmd @@ -113,6 +115,7 @@ updf upgrade uri US902 +US915 user version web_port diff --git a/src/lgwsim.c b/src/lgwsim.c index 1f707c8..23d310d 100644 --- a/src/lgwsim.c +++ b/src/lgwsim.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -387,6 +387,7 @@ int lgw_rxrf_setconf (uint8_t rf_chain, struct lgw_conf_rxrf_s conf) { return LGW_HAL_SUCCESS; } +const uint8_t ifmod_config[LGW_IF_CHAIN_NB] = LGW_IFMODEM_CONFIG; #define LGW_RF_RX_BANDWIDTH_125KHZ 925000 /* for 125KHz channels */ #define LGW_RF_RX_BANDWIDTH_250KHZ 1000000 /* for 250KHz channels */ diff --git a/src/log.c b/src/log.c index 5783ddd..f126bf0 100644 --- a/src/log.c +++ b/src/log.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -51,7 +51,7 @@ const char* MODSTR[] = { [MOD_CUP/8]= "CUP", [MOD_SYS/8]= "SYS", [MOD_TCE/8]= "TCE", - [MOD_TST/8]= "TST", + [MOD_HAL/8]= "HAL", [MOD_SIO/8]= "___", [MOD_SYN/8]= "SYN", [MOD_GPS/8]= "GPS", @@ -159,6 +159,13 @@ void log_msg (u1_t mod_level, const char* fmt, ...) { va_end(ap); } +void log_hal (u1_t level, const char* fmt, ...) { + va_list ap; + va_start(ap, fmt); + log_vmsg(MOD_HAL|level, fmt, ap); + va_end(ap); +} + int log_special (u1_t mod_level, dbuf_t* b) { if( !log_shallLog(mod_level) ) return 0; diff --git a/src/lora.c b/src/lora.c index 3ad023a..4d63baa 100644 --- a/src/lora.c +++ b/src/lora.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -211,7 +211,7 @@ void s2e_make_beacon (uint8_t* layout, sL_t epoch_secs, int infodesc, double lat int crc1 = crc16_no_table(&pdu[0],infodesc_off-2); int crc2 = crc16_no_table(&pdu[infodesc_off], bcn_len-2-infodesc_off); for( int i=0; i<2; i++ ) { - pdu[infodesc_off-2] = crc1>>(8*i); - pdu[bcn_len-2] = crc2>>(8*i); + pdu[infodesc_off-2+i] = crc1>>(8*i); + pdu[bcn_len-2+i] = crc2>>(8*i); } } diff --git a/src/net.c b/src/net.c index c14953b..c0691a0 100644 --- a/src/net.c +++ b/src/net.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -341,6 +341,7 @@ static int writeData (conn_t* conn) { } return IO_WRPEND; } + LOG(MOD_AIO|XDEBUG, "[%d] socket write bytes=%d", conn->netctx.fd, ret); conn->wpos += ret; } return IO_WRDONE; @@ -420,6 +421,7 @@ static int readData (conn_t* conn, int mode) { } return IO_RDPEND; } + LOG(MOD_AIO|XDEBUG, "[%d] socket read bytes=%d", conn->netctx.fd, r); conn->rpos += r; } compact: @@ -1097,6 +1099,7 @@ int http_connect (http_t* conn, char* host, char* port) { int n = snprintf((char*)conn->c.wbuf, conn->c.wbufsize, "%s:%s", host, port); conn->c.wfill = conn->c.rbeg = conn->c.rend = n+1; conn->c.state = HTTP_CONNECTED; + rt_yieldTo(&conn->c.tmr, triggerHttpConnectedEv); return 1; } @@ -1423,21 +1426,42 @@ int httpd_parseReqLine (httpd_pstate_t* pstate, dbuf_t* hdr) { } -static int validateAuthToken (str_t s) { - str_t p = s; - while(1) { - int c; - while( ((c = *p++) >= 'a' && c <= 'z') || (c >= 'A' && c<= 'Z') || (c >= '0' && c<='9') || c=='-' || c=='_' ); - if( p==s || c != ':' || p[0] != ' ' ) - return 0; - s = ++p; - while( (c=*p++) != '\r' && c != 0 ); - if( p==s || c==0 || p[0] != '\n' ) - return 0; - if( p[1] == 0 ) - return 1; - s = p = p+1; // next line +static str_t validateAuthToken (str_t s) { + int l = strlen(s); + // Trim empty lines from the end (either \r\n or \n) + while( l>0 && s[l-1]=='\n' ) { + l -= l>1 && s[l-2]=='\r' ? 2 : 1; + } + // Count \n without preceeding \r + int extra = 0; + for( int i = l-1; i>=0; i-- ) { + if( s[i] == '\n' && (i==0 || s[i-1]=='\r') ) + extra += 1; + } + char* w = rt_mallocN(char, l+extra+2+1); + if( l==0 ) { + return w; } + int i=0, j=0; + while( i= 'a' && c <= 'z') || (c >= 'A' && c<= 'Z') || (c >= '0' && c<='9') || c=='-' || c=='_' ) { + w[j++] = c; + } + if( i==fi+1 || c != ':' || s[i] != ' ' ) { + rt_free(w); + return NULL; // field name *must* be followed by COLON SPACE + } + for( i -= 1; iauthtoken = validateAuthToken(dbuf.buf); + rt_free(dbuf.buf); + if( !conn->authtoken ) { + errmsg = "%s%s contains malformed auth token - expecting: {header: value{\\r\\n|\\n}}*"; goto errexit; - } else { - assert(conn->authtoken==NULL); - conn->authtoken = (str_t)dbuf.buf; } } else if( auth == SYS_AUTH_SERVER ) { errmsg = "%s%s has no key+cert configured - running server auth only"; + LOG(MOD_AIO|INFO, errmsg, sys_credcat2str(cred_cat), sys_credset2str(cred_set)); } else if( !tls_setMyCert(tlsconf, elems[SYS_CRED_MYCERT], elemslen[SYS_CRED_MYCERT], @@ -1480,7 +1503,6 @@ int conn_setup_tls (conn_t* conn, int cred_cat, int cred_set, const char* server errmsg = "%s%s key/cert rejected by MBedTLS"; goto errexit; } - LOG(MOD_AIO|INFO, errmsg, sys_credcat2str(cred_cat), sys_credset2str(cred_set)); assert(conn->tlsconf==NULL && conn->tlsctx==NULL); conn->tlsconf = tlsconf; conn->tlsctx = tls_makeSession(tlsconf, servername); diff --git a/src/net.h b/src/net.h index 6865b78..56cd7ba 100644 --- a/src/net.h +++ b/src/net.h @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/ral.c b/src/ral.c index 4fab1ac..c7ceec3 100644 --- a/src/ral.c +++ b/src/ral.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/ral.h b/src/ral.h index c04d92d..4e57a7d 100644 --- a/src/ral.h +++ b/src/ral.h @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/ral_lgw.c b/src/ral_lgw.c index 3e7ac54..c960acc 100644 --- a/src/ral_lgw.c +++ b/src/ral_lgw.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -41,7 +41,8 @@ #include "lgw/loragw_reg.h" #include "lgw/loragw_hal.h" #if defined(CFG_sx1302) -#include "lgw/loragw_sx1302.h" +#include "lgw/loragw_sx1302_timestamp.h" +extern timestamp_counter_t counter_us; // from loragw_sx1302.c #endif // defined(CFG_sx1302) #define RAL_MAX_RXBURST 10 @@ -124,45 +125,54 @@ int ral_rps2sf (rps_t rps) { // In this impl. we return the time the measurement took - smallest values are best values // int ral_getTimesync (u1_t pps_en, sL_t* last_xtime, timesync_t* timesync) { - u4_t pps_xticks; + static u4_t last_pps_xticks; + u4_t pps_xticks = 0; +#if !defined(CFG_sx1302) if( pps_en ) { // First read last latched value - interval between time syncs needs to be >1s so that a PPS could have happened. // Read last latched value - when PPS occurred. If no PPS happened this returns // the time when LGW_GPS_EN was set to 1. lgw_get_trigcnt(&pps_xticks); -#if defined(CFG_sx1302) - sx1302_gps_enable(false); -#else - lgw_reg_w(LGW_GPS_EN, 0); // PPS latch holds current -#endif + // lgw1 has a single xtick register which is either PPS latched or free running. + // We temporarily disable PPS latching to obtain a free running xtick. + lgw_reg_w(LGW_GPS_EN, 0); // PPS latch holds current + } +#endif ustime_t t0 = rt_getTime(); u4_t xticks = 0; + // Obtain current free running xtick #if defined(CFG_sx1302) - lgw_get_instcnt(&xticks); + timestamp_counter_get(&counter_us, &xticks, &pps_xticks); #else lgw_get_trigcnt(&xticks); #endif ustime_t t1 = rt_getTime(); sL_t d = (s4_t)(xticks - *last_xtime); if( d < 0 ) { - LOG(MOD_SYN|CRITICAL, "SX130X time sync roll over - no update for a long time!"); + LOG(MOD_SYN|CRITICAL, + "SX130x time sync roll over - no update for a long time: xticks=0x%08x last_xtime=0x%lX", + xticks, *last_xtime); d += (sL_t)1<<32; } timesync->xtime = *last_xtime += d; timesync->ustime = (t0+t1)/2; + timesync->pps_xtime = 0; // Will be set if pps_en is set and valid PPS observation is available if( pps_en ) { // PPS latch will hold now current xticks -#if defined(CFG_sx1302) - sx1302_gps_enable(true); -#else +#if !defined(CFG_sx1302) lgw_reg_w(LGW_GPS_EN, 1); #endif - timesync->pps_xtime = timesync->xtime + (s4_t)(pps_xticks - xticks); - } else { - // Signal no PPS - timesync->pps_xtime = 0; + // Catch behavior when PPS is lost: + // - pps_xticks = 0 and pps_xticks = const are illegal PPS observations. + // - Upper layer informed by timesync->pps_xtime = 0. + if( pps_xticks && last_pps_xticks != pps_xticks ) { + timesync->pps_xtime = timesync->xtime + (s4_t)(pps_xticks - xticks); + last_pps_xticks = pps_xticks; + } } + LOG(MOD_SYN|XDEBUG, "SYNC: ustime=0x%012lX (Q=%3d): xticks=0x%08x xtime=0x%lX - PPS: pps_xticks=0x%08x (%u) pps_xtime=0x%lX (pps_en=%d)", + timesync->ustime, (int)(t1-t0), xticks, timesync->xtime, pps_xticks, pps_xticks, timesync->pps_xtime, pps_en); return (int)(t1-t0); } @@ -192,10 +202,15 @@ int ral_tx (txjob_t* txjob, s2ctx_t* s2ctx, int nocca) { struct lgw_pkt_tx_s pkt_tx; memset(&pkt_tx, 0, sizeof(pkt_tx)); + pkt_tx.invert_pol = true; + pkt_tx.no_header = false; + if( txjob->preamble == 0 ) { if( txjob->txflags & TXFLAG_BCN ) { pkt_tx.tx_mode = ON_GPS; pkt_tx.preamble = 10; + pkt_tx.invert_pol = false; + pkt_tx.no_header = true; } else { pkt_tx.tx_mode = TIMESTAMPED; pkt_tx.preamble = 8; @@ -210,9 +225,7 @@ int ral_tx (txjob_t* txjob, s2ctx_t* s2ctx, int nocca) { pkt_tx.rf_chain = 0; pkt_tx.rf_power = (float)(txjob->txpow - txpowAdjust) / TXPOW_SCALE; pkt_tx.coderate = CR_LORA_4_5; - pkt_tx.invert_pol = true; pkt_tx.no_crc = !txjob->addcrc; - pkt_tx.no_header = false; pkt_tx.size = txjob->len; memcpy(pkt_tx.payload, &s2ctx->txq.txdata[txjob->off], pkt_tx.size); @@ -260,6 +273,28 @@ void ral_txabort (u1_t txunit) { #endif } +static void log_rawpkt(u1_t level, str_t msg, struct lgw_pkt_rx_s * pkt_rx) { + LOG(MOD_RAL|level, "%s[CRC %s] %^.3F %.2f/%.1f %R (mod=%d/dr=%d/bw=%d) xtick=%08x (%u) %d bytes: %64H", + msg, + pkt_rx->status == STAT_CRC_OK ? "OK" : "FAIL", + pkt_rx->freq_hz, + pkt_rx->snr, +#if defined(CFG_sx1302) + pkt_rx->rssis, +#else + pkt_rx->rssi, +#endif + ral_lgw2rps(pkt_rx), + pkt_rx->modulation, + pkt_rx->datarate, + pkt_rx->bandwidth, + pkt_rx->count_us, + pkt_rx->count_us, + pkt_rx->size, + pkt_rx->size, pkt_rx->payload + ); +} + //ATTR_FASTCODE static void rxpolling (tmr_t* tmr) { int rounds = 0; @@ -273,23 +308,25 @@ static void rxpolling (tmr_t* tmr) { if( n==0 ) { break; } - LOG(XDEBUG, "RX mod=%s f=%d bw=%d sz=%d dr=%d %H", pkt_rx.modulation == 0x10 ? "LORA" : "FSK", pkt_rx.freq_hz, (int[]){0,500,250,125}[pkt_rx.bandwidth], pkt_rx.size, pkt_rx.datarate, pkt_rx.size, pkt_rx.payload); rxjob_t* rxjob = !TC ? NULL : s2e_nextRxjob(&TC->s2ctx); if( rxjob == NULL ) { - LOG(ERROR, "SX130X RX frame dropped - out of space"); + log_rawpkt(ERROR, "Dropped RX frame - out of space: ", &pkt_rx); break; // Allow to flush RX jobs } if( pkt_rx.status != STAT_CRC_OK ) { - LOG(XDEBUG, "Dropped frame without CRC or with broken CRC"); + if( log_shallLog(MOD_RAL|DEBUG) ) { + log_rawpkt(DEBUG, "", &pkt_rx); + } continue; // silently ignore bad CRC } if( pkt_rx.size > MAX_RXFRAME_LEN ) { // This should not happen since caller provides // space for max frame length - 255 bytes - LOG(MOD_RAL|ERROR, "Frame size (%d) exceeds offered buffer (%d)", pkt_rx.size, MAX_RXFRAME_LEN); + log_rawpkt(ERROR, "Dropped RX frame - frame size too large: ", &pkt_rx); continue; } + memcpy(&TC->s2ctx.rxq.rxdata[rxjob->off], pkt_rx.payload, pkt_rx.size); rxjob->len = pkt_rx.size; rxjob->freq = pkt_rx.freq_hz; @@ -303,9 +340,14 @@ static void rxpolling (tmr_t* tmr) { rps_t rps = ral_lgw2rps(&pkt_rx); rxjob->dr = s2e_rps2dr(&TC->s2ctx, rps); if( rxjob->dr == DR_ILLEGAL ) { - LOG(MOD_RAL|ERROR, "Unable to map to an up DR: %R", rps); + log_rawpkt(ERROR, "Dropped RX frame - unable to map to an up DR: ", &pkt_rx); continue; } + + if( log_shallLog(MOD_RAL|XDEBUG) ) { + log_rawpkt(XDEBUG, "", &pkt_rx); + } + s2e_addRxjob(&TC->s2ctx, rxjob); } @@ -367,10 +409,10 @@ void ral_ini() { } void ral_stop() { - lgw_stop(); + rt_clrTimer(&syncTmr); last_xtime = 0; rt_clrTimer(&rxpollTmr); - rt_clrTimer(&syncTmr); + lgw_stop(); } #endif // defined(CFG_ral_lgw) diff --git a/src/ral_lgw2.c b/src/ral_lgw2.c index 8dd9c39..7d7d24f 100644 --- a/src/ral_lgw2.c +++ b/src/ral_lgw2.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -135,6 +135,7 @@ int ral_rps2sf (rps_t rps) { // In this impl. we return the time the measurement took - smallest values are best values // int ral_getTimesync (u1_t pps_en, sL_t* last_xtime, timesync_t* timesync) { + static u4_t last_pps_xticks; u4_t pps_xticks; if( pps_en ) { // Note: we only get a proper latched value if a PPS egde was detected while @@ -142,9 +143,6 @@ int ral_getTimesync (u1_t pps_en, sL_t* last_xtime, timesync_t* timesync) { // Therefore, read the latch value at the very beginning after a >1sec delay if( sx1301ar_get_trigcnt(SX1301AR_BOARD_MASTER, &pps_xticks) != 0 ) goto failed; - } else { - // Signal no PPS - timesync->pps_xtime = 0; } u4_t hs_pps = 0; if( sx1301ar_get_trighs(SX1301AR_BOARD_MASTER, &hs_pps) != 0 ) hs_pps = 0; @@ -159,18 +157,19 @@ int ral_getTimesync (u1_t pps_en, sL_t* last_xtime, timesync_t* timesync) { sL_t d = (s4_t)(xticks - *last_xtime); if( d < 0 ) { LOG(MOD_SYN|CRITICAL, - "SX1301 time sync roll over - no update for a long time: xticks=0x%lX last_xtime=%0xlX", + "SX1301 time sync roll over - no update for a long time: xticks=0x%08x last_xtime=0x%lX", xticks, *last_xtime); d += (sL_t)1<<32; } timesync->xtime = *last_xtime += d; timesync->ustime = (t0+t1)/2; - if( pps_en ) { + timesync->pps_xtime = 0; // Will be set if pps_en is set and valid PPS observation is available + if( pps_en && pps_xticks && last_pps_xticks != pps_xticks ) { timesync->pps_xtime = timesync->xtime + (s4_t)(pps_xticks - xticks); - } else { - // Signal no PPS - timesync->pps_xtime = 0; + last_pps_xticks = pps_xticks; } + LOG(MOD_SYN|XDEBUG, "SYNC: ustime=0x%012lX (Q=%3d): xticks=0x%08x xtime=0x%lX - PPS: pps_xticks=0x%08x (%u) pps_xtime=0x%lX (pps_en=%d)", + timesync->ustime, (int)(t1-t0), xticks, timesync->xtime, pps_xticks, pps_xticks, timesync->pps_xtime, pps_en); return (int)(t1-t0); failed: LOG(MOD_SYN|CRITICAL, "SX1301 time sync failed: %s", sx1301ar_err_message(sx1301ar_errno)); @@ -193,10 +192,15 @@ u1_t ral_altAntennas (u1_t txunit) { int ral_tx (txjob_t* txjob, s2ctx_t* s2ctx, int nocca) { sx1301ar_tx_pkt_t pkt_tx = sx1301ar_init_tx_pkt(); + pkt_tx.invert_pol = true; + pkt_tx.no_header = false; + if( txjob->preamble == 0 ) { if( txjob->txflags & TXFLAG_BCN ) { pkt_tx.tx_mode = TX_ON_GPS; pkt_tx.preamble = 10; + pkt_tx.invert_pol = false; + pkt_tx.no_header = true; } else { pkt_tx.tx_mode = TX_TIMESTAMPED; pkt_tx.preamble = 8; @@ -211,10 +215,8 @@ int ral_tx (txjob_t* txjob, s2ctx_t* s2ctx, int nocca) { pkt_tx.rf_chain = 0; pkt_tx.rf_power = (float)(txjob->txpow - txpowAdjust) / TXPOW_SCALE; pkt_tx.coderate = CR_4_5; - pkt_tx.invert_pol = true; pkt_tx.no_crc = !txjob->addcrc; - pkt_tx.no_header = false; - pkt_tx.size = txjob->len; + pkt_tx.size = txjob->len; memcpy(pkt_tx.payload, &s2ctx->txq.txdata[txjob->off], pkt_tx.size); // NOTE: nocca not possible to implement with current libloragw API diff --git a/src/rt.c b/src/rt.c index c7549bc..a5f81cd 100644 --- a/src/rt.c +++ b/src/rt.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -243,12 +243,12 @@ void* _rt_malloc(int size, int zero) { void* _rt_malloc_d(int size, int zero, const char* f, int l) { void* p = _rt_malloc(size, zero); - LOG (XDEBUG, " rt_malloc(%d) %s:%d -> %p", size, f, l, p); + // LOG (XDEBUG, " rt_malloc(%d) %s:%d -> %p", size, f, l, p); return p; } void _rt_free_d (void* p, const char* f, int l) { - LOG (XDEBUG, " rt_free() %s:%d -> %p", f, l, p); + // LOG (XDEBUG, " rt_free() %s:%d -> %p", f, l, p); free(p); } @@ -267,7 +267,7 @@ char* rt_strdupn (str_t s, int n) { char* rt_strdupq (str_t s) { // copy and double quote a string if( s == NULL ) return NULL; int n = strlen(s); - char* s2 = strncpy((char*)_rt_malloc(n+3, 0)+1, s, n)-1; + char* s2 = (char*)memcpy((char*)_rt_malloc(n+3, 0)+1, s, n)-1; s2[0] = s2[n+1] = '"'; s2[n+2] = 0; return s2; diff --git a/src/rt.h b/src/rt.h index c46d275..099d3a1 100644 --- a/src/rt.h +++ b/src/rt.h @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -67,8 +67,14 @@ struct datetime { #define USTIME_MAX ((ustime_t)0x7FFFffffFFFFffff) +#if defined(CFG_dbuf_small) // Max dbuf size 64 KB typedef u2_t doff_t; enum { MAX_DOFF = 0xFFFF }; +#else // Max dbuf size 4 GB +typedef u4_t doff_t; +enum { MAX_DOFF = 0xFFFFFFFF }; +#endif + typedef struct dbuf { char* buf; doff_t bufsize; @@ -111,7 +117,7 @@ void dbuf_free (dbuf_t* b); enum { XDEBUG=0, DEBUG, VERBOSE, INFO, NOTICE, WARNING, ERROR, CRITICAL }; // must be 8! enum { MOD_ANY= 0*8, MOD_RAL= 1*8, MOD_S2E= 2*8, MOD_WSS= 3*8, MOD_JSN= 4*8, MOD_AIO= 5*8, MOD_CUP= 6*8, MOD_SYS= 7*8, - MOD_TCE= 8*8, MOD_TST= 9*8, MOD_SIO=10*8, MOD_SYN=11*8, + MOD_TCE= 8*8, MOD_HAL= 9*8, MOD_SIO=10*8, MOD_SYN=11*8, MOD_GPS=12*8, MOD_SIM=13*8, MOD_WEB=14*8, MOD_ALL=0xF8 }; void log_setSlaveIdx (s1_t idx); diff --git a/src/s2conf.c b/src/s2conf.c index a1f3180..140edb5 100644 --- a/src/s2conf.c +++ b/src/s2conf.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/s2conf.h b/src/s2conf.h index 86de43b..4108d4f 100644 --- a/src/s2conf.h +++ b/src/s2conf.h @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/s2e.c b/src/s2e.c index f8fd7f5..6a9c009 100644 --- a/src/s2e.c +++ b/src/s2e.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -52,7 +52,7 @@ static void s2e_bcntimeout (tmr_t* tmr); static void setDC (s2ctx_t* s2ctx, ustime_t t) { for( u1_t u=0; utxunits[u].dc_eu863bands[i] = t; + s2ctx->txunits[u].dc_eu868bands[i] = t; for( u1_t i=0; itxunits[u].dc_perChnl[i] = t; } @@ -126,7 +126,7 @@ void s2e_addRxjob (s2ctx_t* s2ctx, rxjob_t* rxjob) { // Duplicate detected - drop the mirror if( (8*rxjob->snr - rxjob->rssi) > (8*p->snr - p->rssi) ) { // Drop previous frame p - LOG(MOD_S2E|DEBUG, "Dropped mirror frame freq=%F snr=%5.1f rssi=%d (vs. freq=%F snr=%5.1f rssi=%d) - DR%d mic=%d (%d byes)", + LOG(MOD_S2E|DEBUG, "Dropped mirror frame freq=%F snr=%5.1f rssi=%d (vs. freq=%F snr=%5.1f rssi=%d) - DR%d mic=%d (%d bytes)", p->freq, p->snr/4.0, -p->rssi, rxjob->freq, rxjob->snr/4.0, -rxjob->rssi, p->dr, (s4_t)rt_rlsbf4(&s2ctx->rxq.rxdata[p->off]+rxjob->len-4), p->len); @@ -134,7 +134,7 @@ void s2e_addRxjob (s2ctx_t* s2ctx, rxjob_t* rxjob) { rxjob = rxq_dropJob(&s2ctx->rxq, p); } else { // else: Drop newly retrieved frame - aka don't commit it - LOG(MOD_S2E|DEBUG, "Dropped mirror frame freq=%F snr=%5.1f rssi=%d (vs. freq=%F snr=%5.1f rssi=%d) - DR%d mic=%d (%d byes)", + LOG(MOD_S2E|DEBUG, "Dropped mirror frame freq=%F snr=%5.1f rssi=%d (vs. freq=%F snr=%5.1f rssi=%d) - DR%d mic=%d (%d bytes)", rxjob-> freq, rxjob->snr/4.0, -rxjob->rssi, p->freq, p->snr/4.0, -p->rssi, rxjob->dr, (s4_t)rt_rlsbf4(&s2ctx->rxq.rxdata[rxjob->off]+rxjob->len-4), rxjob->len); } @@ -205,7 +205,7 @@ void s2e_flushRxjobs (s2ctx_t* s2ctx) { // -------------------------------------------------------------------------------- -static const u2_t DC_EU863BAND_RATE[] = { +static const u2_t DC_EU868BAND_RATE[] = { [DC_DECI ]= 10, [DC_CENTI]= 100, [DC_MILLI]= 1000, @@ -289,12 +289,12 @@ static void send_dntxed (s2ctx_t* s2ctx, txjob_t* txjob) { uj_encClose(&sendbuf, '}'); (*s2ctx->sendText)(s2ctx, &sendbuf); } - LOG(MOD_S2E|INFO, "TX %J - %s: %F %.1fdBm ant#%d(%d) DR%d %R frame=%12.4H", + LOG(MOD_S2E|INFO, "TX %J - %s: %F %.1fdBm ant#%d(%d) DR%d %R frame=%12.4H (%u bytes)", txjob, txjob->deveui ? "dntxed" : "on air", txjob->freq, (double)txjob->txpow/TXPOW_SCALE, txjob->txunit, ral_rctx2txunit(txjob->rctx), // sending/receiving antenna txjob->dr, s2e_dr2rps(s2ctx, txjob->dr), - txjob->len, &s2ctx->txq.txdata[txjob->off]); + txjob->len, &s2ctx->txq.txdata[txjob->off], txjob->len); } @@ -366,15 +366,15 @@ static int freq2band (u4_t freq) { } static void update_DC (s2ctx_t* s2ctx, txjob_t* txj) { - if( s2ctx->region == J_EU863 ) { + if( s2ctx->region == J_EU868 ) { u1_t band = freq2band(txj->freq); - ustime_t* dcbands = s2ctx->txunits[txj->txunit].dc_eu863bands; + ustime_t* dcbands = s2ctx->txunits[txj->txunit].dc_eu868bands; ustime_t t = dcbands[band]; // Update unless disabled or blocked if( t != USTIME_MIN && t != USTIME_MAX ) { - dcbands[band] = t = txj->txtime + txj->airtime * DC_EU863BAND_RATE[band]; - LOG(XDEBUG, "DC EU band %d blocked until %>.3T (txtime=%>.3T airtime=%~T)", - DC_EU863BAND_RATE[band], t, txj->txtime, (ustime_t)txj->airtime); + dcbands[band] = t = txj->txtime + txj->airtime * DC_EU868BAND_RATE[band]; + LOG(MOD_S2E|XDEBUG, "DC EU band %d blocked until %>.3T (txtime=%>.3T airtime=%~T)", + DC_EU868BAND_RATE[band], rt_ustime2utc(t), rt_ustime2utc(txj->txtime), (ustime_t)txj->airtime); } } int dnchnl = txj->dnchnl; @@ -383,8 +383,8 @@ static void update_DC (s2ctx_t* s2ctx, txjob_t* txj) { // Update unless disabled or blocked if( t != USTIME_MIN && t != USTIME_MAX ) { dclist[dnchnl] = t = txj->txtime + txj->airtime * s2ctx->dc_chnlRate; - LOG(XDEBUG, "DC dnchnl %d blocked until %>.3T (txtime=%>.3T airtime=%~T)", - dnchnl, t, txj->txtime, (ustime_t)txj->airtime); + LOG(MOD_S2E|XDEBUG, "DC dnchnl %d blocked until %>.3T (txtime=%>.3T airtime=%~T)", + dnchnl, rt_ustime2utc(t), rt_ustime2utc(txj->txtime), (ustime_t)txj->airtime); } } @@ -474,9 +474,9 @@ static int altTxTime (s2ctx_t* s2ctx, txjob_t* txjob, ustime_t earliest) { } -static int s2e_canTxEU863 (s2ctx_t* s2ctx, txjob_t* txjob, int* ccaDisabled) { +static int s2e_canTxEU868 (s2ctx_t* s2ctx, txjob_t* txjob, int* ccaDisabled) { ustime_t txtime = txjob->txtime; - ustime_t band_exp = s2ctx->txunits[txjob->txunit].dc_eu863bands[freq2band(txjob->freq)]; + ustime_t band_exp = s2ctx->txunits[txjob->txunit].dc_eu868bands[freq2band(txjob->freq)]; if( txtime >= band_exp ) { return 1; // clear channel analysis not required @@ -497,7 +497,7 @@ static int s2e_canTxPerChnlDC (s2ctx_t* s2ctx, txjob_t* txjob, int* ccaDisabled) txjob, txjob->freq, rt_ustime2utc(txtime), rt_ustime2utc(chfree)); return 0; - ustime_t band_exp = s2ctx->txunits[txjob->txunit].dc_eu863bands[freq2band(txjob->freq)]; + ustime_t band_exp = s2ctx->txunits[txjob->txunit].dc_eu868bands[freq2band(txjob->freq)]; if( txtime >= band_exp ) return 1; // clear channel analysis not required // No DC in band @@ -637,6 +637,7 @@ ustime_t s2e_nextTxAction (s2ctx_t* s2ctx, u1_t txunit) { // Something went wrong - should be emitting LOG(MOD_S2E|ERROR, "%J - radio is not emitting frame - abandoning TX, trying alternative", curr); ral_txabort(txunit); + curr->txflags &= ~TXFLAG_TXING; goto check_alt; } // Looks like it's on air @@ -666,7 +667,8 @@ ustime_t s2e_nextTxAction (s2ctx_t* s2ctx, u1_t txunit) { } // Txtime time too far out Head is TXable - is it time to feed the radio? if( txdelta > TX_AIM_GAP ) { - LOG(MOD_S2E|DEBUG, "%J - next TX start ahead by %~T", curr, txdelta); + LOG(MOD_S2E|DEBUG, "%J - next TX start ahead by %~T (%>.6T)", + curr, txdelta, rt_ustime2utc(curr->txtime)); return curr->txtime - TX_AIM_GAP; } @@ -710,7 +712,13 @@ ustime_t s2e_nextTxAction (s2ctx_t* s2ctx, u1_t txunit) { } } while(1); - LOG(MOD_S2E|VERBOSE, "%J - starting TX in %~T", curr, txdelta); + LOG(MOD_S2E|VERBOSE, "%J - starting TX in %~T: %F %.1fdBm ant#%d(%d) DR%d %R frame=%12.4H (%u bytes)", + curr, txdelta, + curr->freq, (double)curr->txpow/TXPOW_SCALE, + curr->txunit, ral_rctx2txunit(curr->rctx), // sending/receiving antenna + curr->dr, s2e_dr2rps(s2ctx, curr->dr), + curr->len, &s2ctx->txq.txdata[curr->off], curr->len); + int txerr = ral_tx(curr, s2ctx, ccaDisabled); if( txerr != RAL_TX_OK ) { if( txerr == RAL_TX_NOCA ) { @@ -754,20 +762,25 @@ static void s2e_bcntimeout (tmr_t* tmr) { sL_t xtime = ts_ustime2xtime(0, now); sL_t gpstime = ts_xtime2gpstime(xtime); double lat, lon; - int latlon_ok; - ustime_t ahead; - - if( gpstime == 0 || !(latlon_ok = sys_getLatLon(&lat, &lon)) ) { + int latlon_ok = sys_getLatLon(&lat, &lon); + u1_t state = (gpstime ? BCNING_OK:BCNING_NOTIME) | (latlon_ok?BCNING_OK:BCNING_NOPOS); + + if( state != s2ctx->bcn.state ) { + str_t msg = state==BCNING_OK + ? "Beaconing resumed - recovered GPS data: %s %s" + : "Beaconing suspend - missing GPS data: %s %s"; + u1_t change = state ^ s2ctx->bcn.state; + LOG(MOD_S2E|INFO, msg, (change&BCNING_NOTIME)?"time":"", (change&BCNING_NOPOS)?"position":""); + s2ctx->bcn.state = state; + } + if( state != BCNING_OK ) { // We don't have PPS or we are not yet time synced -- retry after a while - ahead = rt_seconds(10); - LOG(MOD_S2E|INFO, "Beaconing suspended for %~T - insufficient GPS data: %s %s", - ahead, gpstime==0?"time":"", latlon_ok?"position":""); - rt_setTimer(tmr, now + ahead); + rt_setTimer(tmr, now + rt_seconds(10)); return; } - + // Next beacon TX time is on upcoming multipl of 128s GPS time which is at least 1s ahead - ahead = BEACON_INTVL - gpstime % BEACON_INTVL; + ustime_t ahead = BEACON_INTVL - gpstime % BEACON_INTVL; sL_t gpstxtime = gpstime + ahead; txjob_t* txjob = txq_reserveJob(&s2ctx->txq); if( txjob == NULL ) { @@ -787,6 +800,7 @@ static void s2e_bcntimeout (tmr_t* tmr) { txjob->txtime = ts_xtime2ustime(txjob->xtime); txjob->freq = s2ctx->bcn.freqs[epoch % (ctrl>>4)]; txjob->dr = ctrl & 0xF; + txjob->addcrc = false; txjob->txflags = TXFLAG_BCN; txjob->prio = PRIO_BEACON; txjob->len = bcn_len; @@ -795,7 +809,7 @@ static void s2e_bcntimeout (tmr_t* tmr) { txq_commitJob(&s2ctx->txq, txjob); if( !s2e_addTxjob(s2ctx, txjob, /*initial placement*/0, now) ) txq_freeJob(&s2ctx->txq, txjob); - + nextbcn: // Sleep until next beacon is 800ms ahead ahead += BEACON_INTVL - rt_millis(800); @@ -848,12 +862,14 @@ static int handle_router_config (s2ctx_t* s2ctx, ujdec_t* D) { ujbuf_t sx130xconf = { .buf=NULL }; ujcrc_t field; u1_t ccaDisabled=0, dcDisabled=0, dwellDisabled=0; // fields not present - s2_t default_txpow = 14 * TXPOW_SCALE; // builtin default + s2_t max_eirp = 100 * TXPOW_SCALE; // special value - no setting requested int jlistlen = 0; chdefl_t upchs = {{0}}; int chslots = 0; s2bcn_t bcn = { 0 }; - + + s2ctx->txpow = 14 * TXPOW_SCALE; // builtin default + while( (field = uj_nextField(D)) ) { switch(field) { case J_freq_range: { @@ -901,8 +917,8 @@ static int handle_router_config (s2ctx_t* s2ctx, ujdec_t* D) { BWNIL, upchs.rps[insert-1].minSF, upchs.rps[insert-1].maxSF); insert--; } - int minDR = (uj_nextSlot(D), uj_intRange(D, 0, DR_CNT-1)); - int maxDR = (uj_nextSlot(D), uj_intRange(D, 0, DR_CNT-1)); + int minDR = (uj_nextSlot(D), uj_intRange(D, 0, 8-1)); // Currently all upchannel DRs must be specified within DRs 0-7 + int maxDR = (uj_nextSlot(D), uj_intRange(D, 0, 8-1)); // Currently all upchannel DRs must be specified within DRs 0-7 upch_insert(&upchs, insert, freq, BWNIL, minDR, maxDR); uj_exitArray(D); chslots++; @@ -955,12 +971,16 @@ static int handle_router_config (s2ctx_t* s2ctx, ujdec_t* D) { break; } case J_region: { - const char* s = uj_str(D); - snprintf(s2ctx->region_s, sizeof(s2ctx->region_s), "%s", s); - s2ctx->region = D->str.crc; - switch( s2ctx->region ) { - case J_EU863: { - s2ctx->canTx = s2e_canTxEU863; + const char* region_s = uj_str(D); + ujcrc_t region = D->str.crc; + switch( region ) { + case J_EU863: { // non-std obsolete naming + region = J_EU868; + region_s = "EU868"; + // FALL THRU + } + case J_EU868: { // common region name + s2ctx->canTx = s2e_canTxEU868; s2ctx->txpow = 16 * TXPOW_SCALE; s2ctx->txpow2 = 27 * TXPOW_SCALE; s2ctx->txpow2_freq[0] = 869400000; @@ -983,25 +1003,44 @@ static int handle_router_config (s2ctx_t* s2ctx, ujdec_t* D) { resetDC(s2ctx, 50); // 2% break; } - case J_AS923JP: { + case J_AS923JP: { // non-std obsolete naming + region = J_AS923_1; + region_s = "AS923-1"; + // FALL THRU + } + case J_AS923_1: { // common region name s2ctx->ccaEnabled = 1; s2ctx->canTx = s2e_canTxPerChnlDC; s2ctx->txpow = 13 * TXPOW_SCALE; resetDC(s2ctx, 10); // 10% - break; } - case J_US902: { + case J_US902: { // non-std obsolete naming + region = J_US915; + region_s = "US915"; + // FALL THRU + } + case J_US915: { // common region name + s2ctx->txpow = 26 * TXPOW_SCALE; + break; + } + case J_AU915: { s2ctx->txpow = 30 * TXPOW_SCALE; break; } + default: { + LOG(MOD_S2E|WARNING, "Unrecognized region: %s - ignored", region_s); + s2ctx->txpow = 14 * TXPOW_SCALE; + region = 0; + break; + } } + snprintf(s2ctx->region_s, sizeof(s2ctx->region_s), "%s", region_s); + s2ctx->region = region; break; } - case J_max_eirp: { - // Generic device level max TX power - in general lower then what the GW can do - // Unless we get more specific limits we stick with that - default_txpow = (s2_t)(uj_num(D) * TXPOW_SCALE); + case J_max_eirp: { // Request a specific max value - see below for if it takes effect + max_eirp = (s2_t)(uj_num(D) * TXPOW_SCALE); break; } case J_MuxTime: { @@ -1146,37 +1185,43 @@ static int handle_router_config (s2ctx_t* s2ctx, ujdec_t* D) { if( ccaDisabled ) s2e_ccaDisabled = ccaDisabled & 2; if( dcDisabled ) s2e_dcDisabled = dcDisabled & 2; if( dwellDisabled ) s2e_dwellDisabled = dwellDisabled & 2; - if( s2ctx->txpow == 0 ) { - // No region specific settings, go with device/builtin default - s2ctx->txpow = default_txpow; + if( max_eirp != 100*TXPOW_SCALE ) { + if( s2ctx->region==0 || max_eirp < s2ctx->txpow ) { + // If no region specified use max_eirp whatever the value + // If a region was specified (unknown region = 14dBm) then only allow lowering + s2ctx->txpow = max_eirp; + } + if( max_eirp < s2ctx->txpow2 ) { + s2ctx->txpow2 = max_eirp; + } } LOG(MOD_S2E|INFO, "Configuring for region: %s%s -- %F..%F", s2ctx->region_s, s2ctx->ccaEnabled ? " (CCA)":"", s2ctx->min_freq, s2ctx->max_freq); - if( log_shallLog(MOD_S2E|VERBOSE) ) { + if( log_shallLog(MOD_S2E|INFO) ) { for( int dr=0; dr<16; dr++ ) { int rps = s2ctx->dr_defs[dr]; if( rps == RPS_ILLEGAL ) { - LOG(MOD_S2E|VERBOSE, " DR%-2d undefined", dr); + LOG(MOD_S2E|INFO, " DR%-2d undefined", dr); } else { - LOG(MOD_S2E|VERBOSE, " DR%-2d %R %s", dr, rps, rps & RPS_DNONLY ? "(DN only)" : ""); + LOG(MOD_S2E|INFO, " DR%-2d %R %s", dr, rps, rps & RPS_DNONLY ? "(DN only)" : ""); } } - LOG(MOD_S2E|VERBOSE, + LOG(MOD_S2E|INFO, " TX power: %.1f dBm EIRP", s2ctx->txpow/(double)TXPOW_SCALE); - if( s2ctx->txpow2 ) { - LOG(MOD_S2E|VERBOSE, " %.1f dBm EIRP for %F..%F", + if( s2ctx->txpow2_freq[0] ) { + LOG(MOD_S2E|INFO, " %.1f dBm EIRP for %F..%F", s2ctx->txpow2/(double)TXPOW_SCALE, s2ctx->txpow2_freq[0], s2ctx->txpow2_freq[1]); } - LOG(MOD_S2E|VERBOSE, " %s list: %d entries", rt_joineui, jlistlen); - LOG(MOD_S2E|VERBOSE, " NetID filter: %08X-%08X-%08X-%08X", + LOG(MOD_S2E|INFO, " %s list: %d entries", rt_joineui, jlistlen); + LOG(MOD_S2E|INFO, " NetID filter: %08X-%08X-%08X-%08X", s2e_netidFilter[3], s2e_netidFilter[2], s2e_netidFilter[1], s2e_netidFilter[0]); - LOG(MOD_S2E|VERBOSE, " Dev/test settings: nocca=%d nodc=%d nodwell=%d", + LOG(MOD_S2E|INFO, " Dev/test settings: nocca=%d nodc=%d nodwell=%d", (s2e_ccaDisabled!=0), (s2e_dcDisabled!=0), (s2e_dwellDisabled!=0)); } if( (bcn.ctrl&0xF0) != 0 ) { // At least one beacon frequency was specified - LOG(MOD_S2E|VERBOSE, "Beaconing every %~T on %F(%d) @ DR%d (frame layout %d/%d/%d)", + LOG(MOD_S2E|INFO, "Beaconing every %~T on %F(%d) @ DR%d (frame layout %d/%d/%d)", BEACON_INTVL, bcn.freqs[0], (bcn.ctrl>>4), bcn.ctrl & 0xF, bcn.layout[0], bcn.layout[1], bcn.layout[2]); @@ -1323,6 +1368,10 @@ void handle_dnmsg (s2ctx_t* s2ctx, ujdec_t* D) { case J_pdu: { uj_str(D); int xlen = D->str.len/2; + if( xlen > 255 ) { + uj_error(D, "TX pdu too large. Maximum is 255 bytes."); + return; + } u1_t* p = txq_reserveData(&s2ctx->txq, xlen); if( p == NULL ) { uj_error(D, "Out of TX data space"); @@ -1375,7 +1424,7 @@ void handle_dnmsg (s2ctx_t* s2ctx, ujdec_t* D) { break; } case J_RX2Freq: { - check_dnfreq(s2ctx, D, &txjob->rx2freq, &txjob->dnchnl); + check_dnfreq(s2ctx, D, &txjob->rx2freq, &txjob->dnchnl2); flags |= 0x0800; break; } @@ -1433,8 +1482,10 @@ void handle_dnmsg (s2ctx_t* s2ctx, ujdec_t* D) { txjob->txtime = ts_xtime2ustime(txjob->xtime); } else { - txjob->xtime += txjob->rxdelay * 1000000; - txjob->txtime = ts_xtime2ustime(txjob->xtime); + if( txjob->xtime != 0 ) { + txjob->xtime += txjob->rxdelay * 1000000; + txjob->txtime = ts_xtime2ustime(txjob->xtime); + } if( txjob->freq == 0 ) { // Switch over to RX2: // class A (device class A/C) - no RX1 provided diff --git a/src/s2e.h b/src/s2e.h index fe0d973..de4cc0d 100644 --- a/src/s2e.h +++ b/src/s2e.h @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -91,13 +91,20 @@ enum { DR_CNT = 16 }; enum { DR_ILLEGAL = 16 }; typedef struct s2txunit { - ustime_t dc_eu863bands[DC_NUM_BANDS]; + ustime_t dc_eu868bands[DC_NUM_BANDS]; ustime_t dc_perChnl[MAX_DNCHNLS+1]; txidx_t head; tmr_t timer; } s2txunit_t; +enum { + BCNING_OK = 0x00, // beaconing enabled & running + BCNING_NOTIME = 0x01, // missing GPS/PPS time + BCNING_NOPOS = 0x02 // missing GW position +}; + typedef struct s2bcn { + u1_t state; // track failure states u1_t ctrl; // 0x0F => DR, 0xF0 = n frequencies u1_t layout[3]; // time_off, infodesc_off, bcn_len u4_t freqs[8]; // 1 or up to 8 frequencies diff --git a/src/selftest_fs.c b/src/selftest_fs.c index 01222c1..62cac6d 100644 --- a/src/selftest_fs.c +++ b/src/selftest_fs.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/selftest_lora.c b/src/selftest_lora.c index 159786e..fd580f5 100644 --- a/src/selftest_lora.c +++ b/src/selftest_lora.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/selftest_rt.c b/src/selftest_rt.c index bde790c..b663f57 100644 --- a/src/selftest_rt.c +++ b/src/selftest_rt.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/selftest_ujdec.c b/src/selftest_ujdec.c index 7b6d93e..ea7a4c0 100644 --- a/src/selftest_ujdec.c +++ b/src/selftest_ujdec.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -217,7 +217,7 @@ static void test_simple_values() { static const char* S2 = "{ \ \"AS923\": 123, \ - \"EU863\": true \ + \"EU868\": true \ }"; static void test_S2() { @@ -237,7 +237,7 @@ static void test_S2() { TCHECK( UJ_UNUM == uj_nextValue(&D) ); break; } - case J_EU863: { + case J_EU868: { TCHECK( UJ_BOOL == uj_nextValue(&D) ); break; } @@ -253,7 +253,7 @@ static void test_S2() { static char* S3 = "[ \ \"AS923\", 123, \ - \"EU863\", true \ + \"EU868\", true \ ]"; static void test_S3() { @@ -281,7 +281,7 @@ static void test_S3() { break; } case 2: { - TCHECK( UJ_STRING == uj_nextValue(&D) && D.str.crc == J_EU863 ); + TCHECK( UJ_STRING == uj_nextValue(&D) && D.str.crc == J_EU868 ); break; } case 3: { @@ -557,10 +557,10 @@ static void test_sugar() { uj_keyword(&D); TFAIL("G15"); // LCOV_EXCL_LINE } - iniDecoder(&D,"\"EU863\""); + iniDecoder(&D,"\"EU868\""); if( uj_decode(&D) ) TFAIL("G16"); // LCOV_EXCL_LINE - TCHECK(J_EU863 == uj_keyword(&D)); + TCHECK(J_EU868 == uj_keyword(&D)); // ---------- uj_hexstr u1_t buf[6]; @@ -595,10 +595,10 @@ static void test_sugar() { if( uj_decode(&D) ) TFAIL("G30"); // LCOV_EXCL_LINE TCHECK(0 == uj_msgtype(&D)); - iniDecoder(&D,"{\"msgtype\":\"EU863\"}"); + iniDecoder(&D,"{\"msgtype\":\"EU868\"}"); if( uj_decode(&D) ) TFAIL("G31"); // LCOV_EXCL_LINE - TCHECK(J_EU863 == uj_msgtype(&D)); + TCHECK(J_EU868 == uj_msgtype(&D)); iniDecoder(&D,"{\"msgtyp\":\"msgtyp\"}"); if( uj_decode(&D) ) TFAIL("G31"); // LCOV_EXCL_LINE @@ -607,10 +607,10 @@ static void test_sugar() { if( uj_decode(&D) ) TFAIL("G31"); // LCOV_EXCL_LINE TCHECK(0 == uj_msgtype(&D)); - iniDecoder(&D,"{\"msgtype\":\"EU\\\"\",\"msgtype\":\"EU863\"}"); + iniDecoder(&D,"{\"msgtype\":\"EU\\\"\",\"msgtype\":\"EU868\"}"); if( uj_decode(&D) ) TFAIL("G31"); // LCOV_EXCL_LINE - TCHECK(J_EU863 == uj_msgtype(&D)); + TCHECK(J_EU868 == uj_msgtype(&D)); } diff --git a/src/selftest_ujenc.c b/src/selftest_ujenc.c index eb7dae4..3f4af8e 100644 --- a/src/selftest_ujenc.c +++ b/src/selftest_ujenc.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/selftest_xprintf.c b/src/selftest_xprintf.c index 95818f9..7747875 100644 --- a/src/selftest_xprintf.c +++ b/src/selftest_xprintf.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/selftest_xq.c b/src/selftest_xq.c index 8c4be9a..3cd78d0 100644 --- a/src/selftest_xq.c +++ b/src/selftest_xq.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/selftests.c b/src/selftests.c index 1e27b6e..fbcffe6 100644 --- a/src/selftests.c +++ b/src/selftests.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/selftests.h b/src/selftests.h index d3860e5..db448ab 100644 --- a/src/selftests.h +++ b/src/selftests.h @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/sx1301v2conf.c b/src/sx1301v2conf.c index a7d63ad..653ae26 100644 --- a/src/sx1301v2conf.c +++ b/src/sx1301v2conf.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -243,7 +243,7 @@ static void parse_SX1301_conf (ujdec_t* D, sx1301ar_chip_cfg_t* chipconf, sx1301 static void setDevice (struct board_conf* boardconf, str_t device) { - str_t dev = sys_radioDevice(device); + str_t dev = sys_radioDevice(device, NULL); int sz = sizeof(boardconf->device); int n = snprintf(boardconf->device, sz, "%s", dev); if( n > sz-1 ) @@ -393,7 +393,7 @@ static int setup_LBT (struct sx1301v2conf* sx1301v2conf, u4_t cca_region) { u2_t scantime_us = 0; s1_t rssi_target = 0; - if( cca_region == J_AS923JP ) { + if( cca_region == J_AS923_1 ) { scantime_us = 5000; rssi_target = -80; } @@ -660,23 +660,26 @@ static void dump_boardConf (int bid, sx1301ar_board_cfg_t* c) { ); } } + log_flushIO(); } static void dump_chipConf (int chipid, sx1301ar_chip_cfg_t* c) { if( !c->enable ) { LOG(MOD_RAL|VERBOSE, "SX1301#%d : disabled", chipid); - return; + } else { + LOG(MOD_RAL|VERBOSE, + "SX1301#%d : %^8F rf_chain=%d", + chipid, + c->freq_hz, + c->rf_chain); } - LOG(MOD_RAL|VERBOSE, - "SX1301#%d : %^8F rf_chain=%d", - chipid, - c->freq_hz, - c->rf_chain); + log_flushIO(); } static void dump_chanConf (int chipid, int chanid, sx1301ar_chan_cfg_t* c) { if( ! c->enable ) { LOG(MOD_RAL|VERBOSE, " ch %d,%d : disabled", chipid, chanid); + log_flushIO(); return; } if( chanid == SX1301AR_CHIP_FSK_IDX ) { @@ -686,6 +689,7 @@ static void dump_chanConf (int chipid, int chanid, sx1301ar_chan_cfg_t* c) { chanid, c->freq_hz, c->modrate); + log_flushIO(); return; } LOG(MOD_RAL|VERBOSE, @@ -696,6 +700,7 @@ static void dump_chanConf (int chipid, int chanid, sx1301ar_chan_cfg_t* c) { sx1301ar_bw_enum2nb(c->bandwidth), sx1301ar_sf_min_enum2nb(c->modrate), sx1301ar_sf_max_enum2nb(c->modrate)); + log_flushIO(); } diff --git a/src/sx1301v2conf.h b/src/sx1301v2conf.h index 99d9ee0..8a6438d 100644 --- a/src/sx1301v2conf.h +++ b/src/sx1301v2conf.h @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/sx130xconf.c b/src/sx130xconf.c index 02258d6..b7a33b0 100644 --- a/src/sx130xconf.c +++ b/src/sx130xconf.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -42,6 +42,8 @@ #define SX130X_RFE_MAX 400000 // Max if offset 400kHz +extern const uint8_t ifmod_config[LGW_IF_CHAIN_NB]; + static void parse_tx_gain_lut (ujdec_t* D, struct lgw_tx_gain_lut_s* txlut) { int slot; uj_enterArray(D); @@ -142,7 +144,7 @@ static void parse_rfconf (ujdec_t* D, struct sx130xconf* sx130xconf, int rfidx) break; } case J_rssi_tcomp: { - parse_rssi_tcomp(D, &sx130xconf->rfconf->rssi_tcomp); + parse_rssi_tcomp(D, &rfconf->rssi_tcomp); break; } #endif @@ -215,14 +217,16 @@ static void parse_ifconf (ujdec_t* D, struct lgw_conf_rxif_s* ifconf) { } static void setDevice (struct sx130xconf* sx130xconf, str_t device) { - str_t dev = sys_radioDevice(device); + u1_t comtype; + str_t dev = sys_radioDevice(device, &comtype); int sz = sizeof(sx130xconf->device); int n = snprintf(sx130xconf->device, sz, "%s", dev); if( n > sz-1 ) LOG(ERROR, "Device string too long (max %d chars): %s", sz-1, dev); #if defined(CFG_sx1302) - sz = sizeof(sx130xconf->boardconf.spidev_path); - n = snprintf(sx130xconf->boardconf.spidev_path, sz, "%s", dev); + sx130xconf->boardconf.com_type = (comtype == COMTYPE_SPI) ? LGW_COM_SPI : LGW_COM_USB; + sz = sizeof(sx130xconf->boardconf.com_path); + n = snprintf(sx130xconf->boardconf.com_path, sz, "%s", dev); if( n > sz-1 ) LOG(ERROR, "Device string too long (max %d chars): %s", sz-1, dev); #endif @@ -346,7 +350,7 @@ static int setup_LBT (struct sx130xconf* sx130xconf, u4_t cca_region) { #if !defined(CFG_sx1302) // For now sx1302 does not support CCA u2_t scantime_us = 0; - if( cca_region == J_AS923JP ) { + if( cca_region == J_AS923_1 ) { scantime_us = 5000; sx130xconf->lbt.rssi_target = -80; } @@ -489,6 +493,136 @@ int sx130xconf_challoc (struct sx130xconf* sx130xconf, chdefl_t* upchs) { return ral_challoc(upchs, sx130xconf_challoc_cb, sx130xconf); } +static void dump_boardConf (struct lgw_conf_board_s* board) { +#if defined(CFG_sx1302) + LOG(MOD_RAL|INFO, "[LGW sx1302] full_duplex=%d clksrc=%d lorawan_public=%d", + board->full_duplex, + board->clksrc, + board->lorawan_public + ); +#else + LOG(MOD_RAL|INFO, "[LGW %s] clksrc=%d lorawan_public=%d", +#if defined(CFG_smtcpico) + "smtcpico", +#else + "lgw1", +#endif + board->clksrc, + board->lorawan_public + ); +#endif + log_flushIO(); +} + +static void dump_txLut (struct lgw_tx_gain_lut_s* txlut) { + LOG(MOD_RAL|DEBUG, "SX130x txlut table (%d entries)", txlut->size); + for( int i=0; isize; i++ ) { +#if !defined(CFG_sx1302) + LOG(MOD_RAL|INFO, + "SX1301 txlut %2d: dig_gain=%d pa_gain=%d dac_gain=%d mix_gain=%d rf_power=%d", i, + txlut->lut[i].dig_gain, + txlut->lut[i].pa_gain, + txlut->lut[i].dac_gain, + txlut->lut[i].mix_gain, + txlut->lut[i].rf_power); +#else + LOG(MOD_RAL|INFO, + "SX1302 txlut %2d: rf_power=%d pa_gain=%d pwr_idx=%d", i, + txlut->lut[i].rf_power, + txlut->lut[i].pa_gain, + txlut->lut[i].pwr_idx); +#endif + } + log_flushIO(); +} + +static void dump_rfConf (int chain, struct lgw_conf_rxrf_s* rfconf) { + if( !rfconf->enable ) { + LOG(MOD_RAL|INFO, " RF%d: disabled", chain); + log_flushIO(); + return; + } + LOG(MOD_RAL|INFO, +#if defined(CFG_sx1302) + " RX%s RF%d: %^8F rssi_offset=%+6.01f type=%d rssi_tcomp=%.03f %.03f %.03f %.03f %.03f", +#else + " RX%s RF%d: %^8F rssi_offset=%+6.01f type=%d tx_notch_freq=%d", +#endif + rfconf->tx_enable ? "/TX" : " ", + chain, + rfconf->freq_hz, + rfconf->rssi_offset, + rfconf->type, +#if defined(CFG_sx1302) + rfconf->rssi_tcomp.coeff_a, + rfconf->rssi_tcomp.coeff_b, + rfconf->rssi_tcomp.coeff_c, + rfconf->rssi_tcomp.coeff_d, + rfconf->rssi_tcomp.coeff_e +#else + rfconf->tx_notch_freq +#endif + ); + log_flushIO(); +} + +static void dump_ifConf (int chain, struct lgw_conf_rxrf_s rfconfs[LGW_RF_CHAIN_NB], struct lgw_conf_rxif_s* ifconf) { + if( !ifconf->enable ) { + LOG(MOD_RAL|INFO," channel %1d disabled", chain); + log_flushIO(); + return; + } + if(ifmod_config[chain] == IF_LORA_STD) { + LOG(MOD_RAL|INFO, + " [STD] %1d: %^8F rf=%d freq=%+6.01f datarate=%d bw=%d %s", chain, + rfconfs[ifconf->rf_chain].freq_hz + ifconf->freq_hz, + ifconf->rf_chain, + (float)ifconf->freq_hz/1000, + ifconf->datarate, + ifconf->bandwidth, +#if defined(CFG_sx1302) + (ifconf->implicit_hdr == true) ? "Implicit header" : "Explicit header" +#else + "" +#endif + ); + + } else if (ifmod_config[chain] == IF_FSK_STD) { + LOG(MOD_RAL|INFO, + " [FSK] %1d: %^8F rf=%d freq=%+6.01f datarate=%d bw=%d sync_word=%lX/%d", chain, + rfconfs[ifconf->rf_chain].freq_hz + ifconf->freq_hz, + ifconf->rf_chain, + (float)ifconf->freq_hz/1000, + ifconf->datarate, + ifconf->bandwidth, + ifconf->sync_word, ifconf->sync_word_size); + } else { + LOG(MOD_RAL|INFO, + " [mSF] %1d: %^8F rf=%d freq=%+6.01f datarate=%d", chain, + rfconfs[ifconf->rf_chain].freq_hz + ifconf->freq_hz, + ifconf->rf_chain, + (float)ifconf->freq_hz/1000, + ifconf->datarate); + } + log_flushIO(); +} + +static void dump_lbtConf (struct sx130xconf* sx130xconf) { +#if !defined(CFG_sx1302) + if( sx130xconf->lbt.enable ) { + LOG(MOD_RAL|INFO, "SX130x LBT enabled: rssi_target=%d rssi_offset=%d", + sx130xconf->lbt.rssi_target, sx130xconf->lbt.rssi_offset); + for( int i=0; i < sx130xconf->lbt.nb_channel; i++ ) { + LOG(MOD_RAL|INFO, " %2d: freq=%F scan=%dus", + i, sx130xconf->lbt.channels[i].freq_hz, sx130xconf->lbt.channels[i].scan_time_us); + } + } else { + LOG(MOD_RAL|INFO, "SX130x LBT not enabled"); + } + log_flushIO(); +#endif +} + int sx130xconf_start (struct sx130xconf* sx130xconf, u4_t cca_region) { str_t errmsg = ""; @@ -502,108 +636,16 @@ int sx130xconf_start (struct sx130xconf* sx130xconf, u4_t cca_region) { rt_fatal("Radio device '%s' in use by process: %d%s", sx130xconf->device, pids[0], n>1?".. (and others)":""); #endif // defined(CFG_linux) - LOG(MOD_RAL|VERBOSE,"Connecting to device: %s", sx130xconf->device); #if defined(CFG_smtcpico) + LOG(MOD_RAL|VERBOSE,"Connecting to smtcpico device: %s", sx130xconf->device); // Picocell needs some time to start up from reset before we can connect sys_usleep(rt_millis(250)); - log_flushIO(); // lgw_connect might block - make sure log output is flushed + log_flushIO(); // lgw_connect might block - make sure log output is flushed lgw_connect(sx130xconf->device); sys_usleep(rt_millis(250)); - // Force a reset because MCU software may be in a weird state when we connect the first time -#endif - - if( log_shallLog(MOD_RAL|VERBOSE) ) { - LOG(MOD_RAL|DEBUG, "SX130x txlut table (%d entries)", sx130xconf->txlut.size); - for( int i=0; itxlut.size; i++ ) { -#if !defined(CFG_sx1302) - LOG(MOD_RAL|VERBOSE, - "SX1301 txlut %2d: dig_gain=%d pa_gain=%d dac_gain=%d mix_gain=%d rf_power=%d", i, - sx130xconf->txlut.lut[i].dig_gain, - sx130xconf->txlut.lut[i].pa_gain, - sx130xconf->txlut.lut[i].dac_gain, - sx130xconf->txlut.lut[i].mix_gain, - sx130xconf->txlut.lut[i].rf_power); -#else - LOG(MOD_RAL|VERBOSE, - "SX1302 txlut %2d: rf_power=%d pa_gain=%d pwr_idx=%d", i, - sx130xconf->txlut.lut[i].rf_power, - sx130xconf->txlut.lut[i].pa_gain, - sx130xconf->txlut.lut[i].pwr_idx); #endif - } -#if defined(CFG_sx1302) - LOG(MOD_RAL|VERBOSE, "SX1302 rssi_tcomp: coeff_a=%.03f coeff_b=%.03f coeff_c=%.03f coeff_d=%.03f coeff_e=%.03f\n", - sx130xconf->rfconf->rssi_tcomp.coeff_a, - sx130xconf->rfconf->rssi_tcomp.coeff_b, - sx130xconf->rfconf->rssi_tcomp.coeff_c, - sx130xconf->rfconf->rssi_tcomp.coeff_d, - sx130xconf->rfconf->rssi_tcomp.coeff_e); -#endif - for( int i=0; irfconf[i].enable, - sx130xconf->rfconf[i].freq_hz, - sx130xconf->rfconf[i].rssi_offset, - sx130xconf->rfconf[i].type, - sx130xconf->rfconf[i].tx_enable -#if !defined(CFG_sx1302) - , sx130xconf->rfconf[i].tx_notch_freq -#endif - ); - } - for( int i=0; iifconf[i].enable, - sx130xconf->ifconf[i].rf_chain, - sx130xconf->ifconf[i].freq_hz, - sx130xconf->ifconf[i].bandwidth, - sx130xconf->ifconf[i].datarate, - sx130xconf->ifconf[i].sync_word, sx130xconf->ifconf[i].sync_word_size); -#else - if(i == LGW_MULTI_NB){ - LOG(MOD_RAL|VERBOSE, - "SX1302 ifchain %2d: enable=%d rf_chain=%d freq=%d bw=%d SF=%d sync_word=%lX/%d [STD] %s", i, - sx130xconf->ifconf[i].enable, - sx130xconf->ifconf[i].rf_chain, - sx130xconf->ifconf[i].freq_hz, - sx130xconf->ifconf[i].bandwidth, - sx130xconf->ifconf[i].datarate, - sx130xconf->ifconf[i].sync_word, sx130xconf->ifconf[i].sync_word_size, - (sx130xconf->ifconf[i].implicit_hdr == true) ? "Implicit header" : "Explicit header"); - }else{ - LOG(MOD_RAL|VERBOSE, - "SX1302 ifchain %2d: enable=%d rf_chain=%d freq=%d bw=%d SF=%d sync_word=%lX/%d", i, - sx130xconf->ifconf[i].enable, - sx130xconf->ifconf[i].rf_chain, - sx130xconf->ifconf[i].freq_hz, - sx130xconf->ifconf[i].bandwidth, - sx130xconf->ifconf[i].datarate, - sx130xconf->ifconf[i].sync_word, sx130xconf->ifconf[i].sync_word_size); - } -#endif - } -#if !defined(CFG_sx1302) - if( sx130xconf->lbt.enable ) { - LOG(MOD_RAL|VERBOSE, "SX130x LBT enabled: rssi_target=%d rssi_offset=%d", - sx130xconf->lbt.rssi_target, sx130xconf->lbt.rssi_offset); - for( int i=0; i < sx130xconf->lbt.nb_channel; i++ ) { - LOG(MOD_RAL|VERBOSE, " %2d: freq=%F scan=%dus", - i, sx130xconf->lbt.channels[i].freq_hz, sx130xconf->lbt.channels[i].scan_time_us); - } - } else { - LOG(MOD_RAL|VERBOSE, "SX130x LBT not enabled"); - } -#endif - } - + dump_boardConf(&sx130xconf->boardconf); #if defined(CFG_sx1302) if( lgw_board_setconf(&sx130xconf->boardconf) != LGW_HAL_SUCCESS ) { #else @@ -613,6 +655,7 @@ int sx130xconf_start (struct sx130xconf* sx130xconf, u4_t cca_region) { goto fail; } if( sx130xconf->txlut.size > 0) { + dump_txLut(&sx130xconf->txlut); #if defined(CFG_sx1302) if( lgw_txgain_setconf(0, &sx130xconf->txlut) != LGW_HAL_SUCCESS ) { #else @@ -623,6 +666,7 @@ int sx130xconf_start (struct sx130xconf* sx130xconf, u4_t cca_region) { } } for( int i=0; irfconf[i]); #if defined(CFG_sx1302) if( lgw_rxrf_setconf(i, &sx130xconf->rfconf[i]) != LGW_HAL_SUCCESS ) { #else @@ -634,6 +678,7 @@ int sx130xconf_start (struct sx130xconf* sx130xconf, u4_t cca_region) { } } for( int i=0; irfconf, &sx130xconf->ifconf[i]); #if defined(CFG_sx1302) if( lgw_rxif_setconf(i, &sx130xconf->ifconf[i]) != LGW_HAL_SUCCESS ) { #else @@ -645,18 +690,24 @@ int sx130xconf_start (struct sx130xconf* sx130xconf, u4_t cca_region) { } } + dump_lbtConf(sx130xconf); if( cca_region && !setup_LBT(sx130xconf, cca_region) ) { errmsg = "setup_LBT"; goto fail; } - LOG(MOD_RAL|VERBOSE, "Station device: %s (PPS capture %sabled)", sx130xconf->device, sx130xconf->pps ? "en":"dis"); - log_flushIO(); // flush output since lgw_start may block for quite some time on some concentrators #if defined(CFG_sx1302) + LOG(MOD_RAL|INFO, "Station device: %s:%s (PPS capture %sabled)", + sx130xconf->boardconf.com_type == LGW_COM_USB ? "usb" : "spi", + sx130xconf->device, sx130xconf->pps ? "en":"dis" + ); (void) sys_deviceMode; // TODO: Add device mode to sx1302 hal #else + LOG(MOD_RAL|INFO, "Station device: %s (PPS capture %sabled)", sx130xconf->device, sx130xconf->pps ? "en":"dis"); lgwx_device_mode = sys_deviceMode; #endif + log_flushIO(); // flush output since lgw_start may block for quite some time on some concentrators + ustime_t t0 = rt_getTime(); int err = lgw_start(); if( err != LGW_HAL_SUCCESS ) { @@ -671,7 +722,7 @@ int sx130xconf_start (struct sx130xconf* sx130xconf, u4_t cca_region) { errmsg = "LGW GPS Enable"; goto fail; } - LOG(MOD_RAL|VERBOSE, "Concentrator started (%~T)", rt_getTime()- t0); + LOG(MOD_RAL|INFO, "Concentrator started (%~T)", rt_getTime()- t0); #if defined(CFG_smtcpico) { // Avoid timing issues with picocell MCU firmware - re-adjusts time after first TX diff --git a/src/sx130xconf.h b/src/sx130xconf.h index a1491dc..70531e8 100644 --- a/src/sx130xconf.h +++ b/src/sx130xconf.h @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/sys.c b/src/sys.c index e8fe6ee..9ed2f36 100644 --- a/src/sys.c +++ b/src/sys.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -51,8 +51,6 @@ uL_t protoEUI = 0; uL_t prefixEUI = 1; // 1 -> *:ffe:* MAC => EUI scheme s1_t sys_slaveIdx = -1; -#define sync() - // Standard config files: // {tc,cups}{,-bootstrap,-bak}.{uri,key,crt,trust} // Temporary files: @@ -320,7 +318,7 @@ static int updateConfigFiles (int cat, int rollFwd) { LOG(MOD_SYS|CRITICAL, "Failed to create '%s': %s", taf_upd); return 0; } - sync(); + fs_sync(); for( int ext=0; ext < nFN_EXT; ext++ ) { str_t fn_temp = configFilename(cat, FN_TEMP, ext); str_t fn_reg = configFilename(cat, FN_REG, ext); @@ -329,7 +327,7 @@ static int updateConfigFiles (int cat, int rollFwd) { rt_fatal("Failed to rename '%s' -> '%s': %s", fn_temp, fn_reg, strerror(errno)); } } - sync(); + fs_sync(); fs_unlink(taf_upd); return 1; } @@ -346,7 +344,7 @@ static int backupConfigFiles (int cat, int rollFwd) { LOG(MOD_SYS|CRITICAL, "Failed to create '%s': %s", taf_cpy); return 0; } - sync(); + fs_sync(); str_t unlink_fn = transactionFilename(cat, FN_DON); if( fs_unlink(unlink_fn) == -1 && errno != ENOENT ) { unlink_fail: @@ -375,9 +373,9 @@ static int backupConfigFiles (int cat, int rollFwd) { LOG(MOD_SYS|CRITICAL, "Failed to write '%s': %s", taf_don, strerror(errno)); return 0; // just walk away and keep taf file - copying will be continued with next station restart } - sync(); + fs_sync(); fs_unlink(taf_cpy); - sync(); + fs_sync(); bakDone[cat] = 1; return 1; } @@ -490,7 +488,7 @@ void sys_resetConfigUpdate () { if( fn ) fs_unlink(fn); } } - sync(); + fs_sync(); } void sys_commitConfigUpdate () { @@ -577,13 +575,13 @@ void sys_credComplete (int cred_cat, int len) { data[SYS_CRED_MYKEY] = pendData+ko; datalen[SYS_CRED_MYKEY] = kl; u1_t * p = (u1_t*)pendData; - LOG(INFO, "credComplete - trust_off=%4u, trust_len=%4u %02x %02x %02x %02x %02x %02x %02x %02x", + LOG(MOD_SYS|INFO, " credComplete - trust_off=%4u, trust_len=%4u %02x %02x %02x %02x %02x %02x %02x %02x", to, tl, p[to+0], p[to+1], p[to+2], p[to+3],p[to+4], p[to+5], p[to+6], p[to+7] ); - LOG(INFO, "credComplete - cert_off =%4u, cert_len =%4u %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", + LOG(MOD_SYS|INFO, " credComplete - cert_off =%4u, cert_len =%4u %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", co, cl, p[co-4], p[co-3], p[co-2], p[co-1], p[co+0], p[co+1], p[co+2], p[co+3], p[co+4], p[co+5], p[co+6], p[co+7] ); - LOG(INFO, "credComplete - key_off =%4u, key_len =%4u %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", + LOG(MOD_SYS|INFO, " credComplete - key_off =%4u, key_len =%4u %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", ko, kl, p[ko-4], p[ko-3], p[ko-2], p[ko-1], p[ko+0], p[ko+1], p[ko+2], p[ko+3], p[ko+4], p[ko+5], p[ko+6], p[ko+7] ); if( datalen[SYS_CRED_TRUST] + datalen[SYS_CRED_MYCERT] + datalen[SYS_CRED_MYKEY] > len ) { @@ -651,4 +649,3 @@ void sys_keepAlive (int fd) { err: LOG(MOD_AIO|ERROR, "Failed to set %s=%d: %s", tag, v, strerror(errno)); } - diff --git a/src/sys.h b/src/sys.h index e705ea8..d4036c7 100644 --- a/src/sys.h +++ b/src/sys.h @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -31,6 +31,7 @@ #include "rt.h" +enum { COMTYPE_SPI=0, COMTYPE_USB }; enum { PPS_GPS=0, PPS_FUZZY, PPS_TESTPIN }; extern u1_t sys_modePPS; // special PPS mode? extern u1_t sys_deviceMode; // special mode used for GW regr testing @@ -89,7 +90,7 @@ u4_t sys_crcCred (int cred_cat, int cred_set); void sys_runUpdate (); void sys_abortUpdate (); -str_t sys_radioDevice (str_t device); +str_t sys_radioDevice (str_t device, u1_t* comtype); int sys_runRadioInit (str_t device); int sys_execCommand (ustime_t max_wait, str_t* argv); diff --git a/src/tc.c b/src/tc.c index 5d1d944..86ba7e8 100644 --- a/src/tc.c +++ b/src/tc.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -125,6 +125,8 @@ static void tc_connect_muxs (tc_t* tc) { if( tlsmode == URI_TLS && !conn_setup_tls(&tc->ws, SYS_CRED_TC, SYS_CRED_REG, hostname) ) { goto errexit; } + LOG(MOD_TCE|VERBOSE, "Connecting to MUXS..."); + log_flushIO(); if( !ws_connect(&tc->ws, hostname, port, path) ) { LOG(MOD_TCE|ERROR, "Muxs connect failed - URI: ws%s://%s:%s%s", tlsmode==URI_TLS?"s":"", hostname, port, path); goto errexit; @@ -132,7 +134,6 @@ static void tc_connect_muxs (tc_t* tc) { rt_setTimerCb(&tc->timeout, rt_micros_ahead(TC_TIMEOUT), tc_timeout); tc->ws.evcb = (evcb_t)tc_muxs_connection; tc->tstate = TC_MUXS_REQ_PEND; - LOG(MOD_TCE|VERBOSE, "Connecting to MUXS..."); return; errexit: @@ -322,6 +323,8 @@ void tc_start (tc_t* tc) { goto errexit; } tstate_err = TC_ERR_FAILED; + LOG(MOD_TCE|INFO, "Connecting to INFOS: %s", tcuri); + log_flushIO(); if( !ws_connect(&tc->ws, hostname, port, "/router-info") ) { LOG(MOD_TCE|ERROR, "TC connect failed - URI: %s", tcuri); goto errexit; @@ -329,7 +332,6 @@ void tc_start (tc_t* tc) { rt_setTimerCb(&tc->timeout, rt_seconds_ahead(TC_TIMEOUT), tc_timeout); tc->ws.evcb = (evcb_t)tc_info_request; tc->tstate = TC_INFOS_REQ_PEND; - LOG(MOD_TCE|INFO, "Connecting to INFOS: %s", tcuri); return; errexit: tc_done(tc, tstate_err); diff --git a/src/tc.h b/src/tc.h index f65d179..01c3dd1 100644 --- a/src/tc.h +++ b/src/tc.h @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/timesync.c b/src/timesync.c index 0000216..98bc7c3 100644 --- a/src/timesync.c +++ b/src/timesync.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -105,14 +105,15 @@ static void timesyncReport (int force) { if( !force && now < lastReport + TIMESYNC_REPORTS ) return; lastReport = now; - uL_t pps_ustime = xtime2ustime(×yncs[0], ppsSync.pps_xtime); - LOG(MOD_SYN|INFO, "Time sync: ustime=0x%lX utc=0x%lX gpsOffset=0x%lX ppsOffset=%ld syncQual=%d\n", + uL_t pps_ustime = timesyncs[0].pps_xtime != 0 ? xtime2ustime(×yncs[0], timesyncs[0].pps_xtime) : 0; + LOG(MOD_SYN|INFO, "Time sync: NOW ustime=0x%012lX utc=0x%lX gpsOffset=0x%lX ppsOffset=%ld syncQual=%d\n", now, rt_ustime2utc(now), gpsOffset, ppsOffset, syncQual[0]); - LOG(MOD_SYN|INFO, "Time sync: MCU/SX130X#0 ustime=0x%lX xtime=0x%lX pps_xtime=0x%lX", - timesyncs[0].ustime, timesyncs[0].xtime, timesyncs[0].pps_xtime); + LOG(MOD_SYN|INFO, "Time sync: MCU/SX130X#0 ustime=0x%012lX xtime=0x%lX pps_ustime=0x%lX pps_xtime=0x%lX", + timesyncs[0].ustime, timesyncs[0].xtime, pps_ustime, timesyncs[0].pps_xtime); if( !ppsOffset ) return; - LOG(MOD_SYN|INFO, "Time sync: Last PPS ustime=0x%lX xtime=0x%lX pps_ustime=0x%lX pps_xtime=0x%lX", + pps_ustime = xtime2ustime(×yncs[0], ppsSync.pps_xtime); + LOG(MOD_SYN|INFO, "Time sync: Last PPS ustime=0x%012lX xtime=0x%lX pps_ustime=0x%lX pps_xtime=0x%lX", ppsSync.ustime, ppsSync.xtime, pps_ustime, ppsSync.pps_xtime); if( !gpsOffset ) return; @@ -226,7 +227,7 @@ ustime_t ts_updateTimesync (u1_t txunit, int quality, const timesync_t* curr) { if( abs(drift_ppm) > stats->drift_thres ) { stats->excessive_drift_cnt += 1; if( (stats->excessive_drift_cnt % QUICK_RETRIES) == 0 ) { - LOG(MOD_SYN|ERROR, "Repeated excessive clock drifts between MCU/SX130X#%d (%d retries): %.1fppm (threshold %.1fppm)", + LOG(MOD_SYN|WARNING, "Repeated excessive clock drifts between MCU/SX130X#%d (%d retries): %.1fppm (threshold %.1fppm)", txunit, stats->excessive_drift_cnt, drift_ppm/fPPM_SCALE, stats->drift_thres/fPPM_SCALE); } if( stats->excessive_drift_cnt >= 2*QUICK_RETRIES ) @@ -244,22 +245,29 @@ ustime_t ts_updateTimesync (u1_t txunit, int quality, const timesync_t* curr) { // We are actually tracking PPS - complain if PPS lost s4_t no_pps_secs = (curr->xtime - ppsSync.pps_xtime + PPM/2) / PPM; if( no_pps_secs > no_pps_thres ) { - LOG(MOD_SYN|ERROR, "No PPS pulse for ~%d secs", no_pps_secs); + LOG(MOD_SYN|WARNING, "No PPS pulse for ~%d secs", no_pps_secs); no_pps_thres = no_pps_thres >= NO_PPS_ALARM_MAX ? no_pps_thres + NO_PPS_ALARM_MAX : (u4_t)(no_pps_thres * NO_PPS_ALARM_RATE); } } // We update ppsSync only if we have two consecutive time syncs with valid PPS timestamps - // and if they are apart ~1s - we might be weird values if no PPS pulse occurred during time sync span. - if( !last->pps_xtime || !curr->pps_xtime ) + // and if they are apart ~1s - we might see weird values if no PPS pulse occurred during time sync span. + if( !last->pps_xtime || !curr->pps_xtime ) { goto done; - if( curr->xtime - curr->pps_xtime > PPM+TX_MIN_GAP ) + } + if( curr->xtime - curr->pps_xtime > PPM+TX_MIN_GAP ) { + LOG(MOD_SYN|XDEBUG, "PPS: Rejecting PPS (xtime/pps_xtime spread): curr->xtime=0x%lX curr->pps_xtime=0x%lX diff=%lu (>%u)", + curr->xtime, curr->pps_xtime, curr->xtime - curr->pps_xtime, PPM+TX_MIN_GAP); goto done; // no PPS since last time sync + } sL_t err = (curr->pps_xtime - last->pps_xtime) % PPM; if( err < 0 ) err += PPM; - if( err > MAX_PPS_ERROR && err < PPM-MAX_PPS_ERROR ) + if( err > MAX_PPS_ERROR && err < PPM-MAX_PPS_ERROR ) { + LOG(MOD_SYN|XDEBUG, "PPS: Rejecting PPS (consecutive pps_xtime error): curr->pps_xtime=0x%lX last->pps_xtime=0x%lX diff=%lu", + curr->pps_xtime, last->pps_xtime, curr->pps_xtime - last->pps_xtime); goto done; // out of scope - probably no value latched + } if( !ppsSync.pps_xtime ) LOG(MOD_SYN|INFO, "First PPS pulse acquired"); @@ -282,12 +290,13 @@ ustime_t ts_updateTimesync (u1_t txunit, int quality, const timesync_t* curr) { LOG(MOD_SYN|INFO, "Obtained initial PPS offset (%ld) - starting timesync with LNS", ppsOffset); } else if( abs(ppsOffset-off) > (stats->drift_thres * TIMESYNC_RADIO_INTV)/PPM ) { - LOG(MOD_SYN|INFO, "Changed PPS offset: %ld => %ld (delta: %ld)", ppsOffset, off, off-ppsOffset); + LOG(MOD_SYN|XDEBUG, "Changed PPS offset: %ld => %ld (delta: %ld)", ppsOffset, off, off-ppsOffset); // Adjust ppsOffset to accout for MCU/PPS drift ppsOffset = off; } - // Correct the fractional second of the UTC reference by ppsOffset (expects s-precision UTC time reference) - rt_utcOffset = rt_utcOffset - rt_utcOffset%PPM + (PPM-ppsOffset); + // Correct the fractional second of the UTC reference so it lines up with PPS + ustime_t pps_utctime_us = rt_ustime2utc(pps_ustime) % PPM; + rt_utcOffset += pps_utctime_us < PPM/2 ? -pps_utctime_us : PPM-pps_utctime_us; // Shift timesync into the middle of two PPS pulses // Avoid turning off PPS latching during SX130X sync procedure near the PPS. // We might miss a PPS pulse and a scheduled frame might not be sent. diff --git a/src/timesync.h b/src/timesync.h index f519af0..2e5b007 100644 --- a/src/timesync.h +++ b/src/timesync.h @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/tls.c b/src/tls.c index 69c57db..8aa4ede 100644 --- a/src/tls.c +++ b/src/tls.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -77,7 +77,7 @@ static mbedtls_ctr_drbg_context* assertDBRG () { #ifdef CFG_max_tls_frag_len // Report this only once - at startup - LOG(WARNING, "TLS is using a maximum fragment length of %d bytes", 256 << CFG_max_tls_frag_len); + LOG(MOD_AIO|WARNING, "TLS is using a maximum fragment length of %d bytes", 256 << CFG_max_tls_frag_len); #endif // CFG_max_tls_frag_len return &DBRG->ctr_drbg; @@ -193,7 +193,7 @@ static int _readCAs (mbedtls_x509_crt** pcas, const char* cafile, int len, const if( len <= 0 ) { // Reuse buffer to print cert info before freeing mbedtls_x509_crt_info( (char*)certb, certl, "", cas ); - LOG(INFO,"%s: \n%s", cafile, certb); + LOG(MOD_AIO|INFO,"%s: \n%s", cafile, certb); rt_free(certb); } @@ -234,8 +234,10 @@ int tls_setMyCert (tlsconf_t* conf, const char* cert, int certlen, const char* k log_mbedError(ERROR, ret, "Parsing key"); goto errexit; } - if( keylen <= 0 ) + if( keylen <= 0 ) { rt_free(keyb); + keyb = NULL; + } if( !_readCAs(&conf->mycert, cert, certlen, "my cert") ) goto errexit; conf->mykey = mykey; diff --git a/src/tls.h b/src/tls.h index 9c738ea..5244551 100644 --- a/src/tls.h +++ b/src/tls.h @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/uj.c b/src/uj.c index 4697eb5..12949f7 100644 --- a/src/uj.c +++ b/src/uj.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/uj.h b/src/uj.h index e97efa7..825bf52 100644 --- a/src/uj.h +++ b/src/uj.h @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/web.c b/src/web.c index 0f52067..4d42744 100644 --- a/src/web.c +++ b/src/web.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -114,7 +114,7 @@ static void web_onev (conn_t* _conn, int ev) { case HTTPDEV_REQUEST: { dbuf_t hdr = httpd_getHdr(hd); - + LOG(MOD_WEB|XDEBUG, "Client request: content-length=%d\n%.*s", hd->extra.clen, hdr.bufsize, hdr.buf); httpd_pstate_t pstate; int r = 500; // Note: writing to respbuf overwrites hdr! diff --git a/src/web.h b/src/web.h index 37a7466..19a9842 100644 --- a/src/web.h +++ b/src/web.h @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/ws.h b/src/ws.h index 2f63ffe..5ab3383 100644 --- a/src/ws.h +++ b/src/ws.h @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/xq.c b/src/xq.c index 04aa421..a08a5ee 100644 --- a/src/xq.c +++ b/src/xq.c @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: diff --git a/src/xq.h b/src/xq.h index c218fb8..0824f2c 100644 --- a/src/xq.h +++ b/src/xq.h @@ -1,6 +1,6 @@ /* * --- Revised 3-Clause BSD License --- - * Copyright Semtech Corporation 2020. All rights reserved. + * Copyright Semtech Corporation 2022. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: