#!/bin/bash
# This version is heavily based on the work of mz-fuzzy (https://github.com/mz-fuzzy)
# adapted to work with MySensors project.
# Original work: https://github.com/TMRh20/RF24/blob/master/configure

function help {
cat <<EOF	
configure script for MySensors gateway.
Options:

Help:
    -h, --help                  print this message

SPI driver options:
    --spi-driver=[BCM|SPIDEV]
    --spi-spidev-device=<DEVICE>
                                Device path. [/dev/spidev0.0]

Building options:
    --soc=[BCM2711|BCM2835|BCM2836|BCM2837|AM33XX|A10|A13|A20|H3]
                                SoC type to be used. [configure autodetected]
    --cpu-flags=<CPUFLAGS>      CPU defining/optimizing flags to be used. [configure autodetected]
    --extra-cflags=<CFLAGS>     Extra C flags passed to C compilation. []
    --extra-cxxflags=<CXXFLAGS> Extra C++ flags passed to C++ compilation. []
                                Example: --extra-cxxflags="-DMY_RX_MESSAGE_BUFFER_SIZE=\(32\) -DMY_RF24_DATARATE=\(RF24_2MBPS\)"
    --extra-ldflags=<LDFLAGS>   Extra C flags passed to linking. []
    --c_compiler=<CC>           C compiler. [arm-linux-gnueabihf-gcc][gcc]
    --cxx_compiler=<CXX>        C++ compiler. [arm-linux-gnueabihf-g++][g++]
    --build-dir=<DIR>           Compiler directory to store object files. [build]
    --bin-dir=<DIR>             Compiler directory to store binary files. [bin]
    --arduino-lib-dir=<DIR>     Arduino library directory.
    --no-clean                  Don't clean previous build artifacts.

Installation options:
    --prefix=<PREFIX>           Installation prefix path. [/usr/local]
    --gateway-dir=<DIR>         Gateway files installation directory. [PREFIX/bin]

MySensors options:
    --my-debug=[enable|disable] Enables or disables MySensors core debugging. [enable]
    --my-config-file=<FILE>     Config file path. [/etc/mysensors.conf]
    --my-gateway=[none|ethernet|serial|mqtt]
                                Set the protocol used to communicate with the controller. [ethernet]
    --my-node-id=<ID>           Disable gateway feature and run as a node with the specified id.
    --my-controller-url-address=<URL>
                                Controller or MQTT broker url.
    --my-controller-ip-address=<IP>
                                Controller or MQTT broker ip.
    --my-port=<PORT>            The port to keep open on gateway mode.
                                If gateway is set to mqtt, it sets the broker port.
    --my-serial-port=<PORT>     Serial port.
    --my-serial-baudrate=<BAUD> Serial baud rate. [115200]
    --my-serial-is-pty          Set the serial port to be a pseudo terminal. Use this if you want
                                to connect to a controller running on the same device.
                                You also need to set the symlink name for the PTY device with
                                the --my-serial-port option.
    --my-serial-groupname=<GROUP>
                                Grant access to the specified system group for the serial device.
    --my-mqtt-client-id=<ID>    MQTT client id.
    --my-mqtt-user=<UID>        MQTT user id.
    --my-mqtt-password=<PASS>   MQTT password.
    --my-mqtt-publish-topic-prefix=<PREFIX>
                                MQTT publish topic prefix.
    --my-mqtt-subscribe-topic-prefix=<PREFIX>
                                MQTT subscribe topic prefix.
    --my-transport=[none|rf24|rfm69|rfm95|rs485]
                                Set the transport to be used to communicate with other nodes. [rf24]
    --my-rf24-channel=<0-125>   RF channel for the sensor net. [76]
    --my-rf24-pa-level=[RF24_PA_MAX|RF24_PA_HIGH|RF24_PA_LOW|RF24_PA_MIN]
                                RF24 PA level. [RF24_PA_MAX]
    --my-rf24-ce-pin=<PIN>      Pin number to use for rf24 Chip-Enable.
    --my-rf24-cs-pin=<PIN>      Pin number to use for rf24 Chip-Select.
    --my-rf24-irq-pin=<PIN>     Pin number connected to nRF24L01P IRQ pin.
    --my-rf24-encryption-enabled
                                Enables RF24 encryption.
                                All nodes and gateway must have this enabled, and all must be
                                personalized with the same AES key.
    --my-rx-message-buffer-size=<SIZE>
                                Buffer size for incoming messages when using rf24 interrupts. [20]
    --my-rfm69-frequency=[315|433|865|868|915]
                                RFM69 Module Frequency. [868]
    --my-is-rfm69hw             Enable high-powered rfm69hw.
    --my-rfm69-irq-pin=<PIN>    Pin number connected to RFM69 IRQ pin.
    --my-rfm69-cs-pin=<PIN>     Pin number to use for RFM69 Chip-Select.
    --my-rfm69-encryption-enabled
                                Enables RFM69 encryption.
                                All nodes and gateway must have this enabled, and all must be
                                personalized with the same AES key.
    --my-rfm95-frequency=[169|315|434|868|915]
                                RFM95 Module Frequency. [868]
    --my-rfm95-irq-pin=<PIN>    Pin number connected to RFM95 IRQ pin.
    --my-rfm95-cs-pin=<PIN>     Pin number to use for RFM95 Chip-Select.
    --my-rfm95-encryption-enabled
                                Enables RFM95 encryption.
                                All nodes and gateway must have this enabled, and all must be
                                personalized with the same AES key.
    --my-rs485-serial-port=<PORT>
                                RS485 serial port. You must provide a port.
    --my-rs485-baudrate=<BAUD>  RS485 baudrate. [9600]
    --my-rs485-de-pin=<PIN>     Pin number connected to RS485 driver enable pin.
    --my-rs485-max-msg-length=<LENGTH>
                                The maximum message length used for RS485. [40]
    --my-leds-err-pin=<PIN>     Error LED pin.
    --my-leds-rx-pin=<PIN>      Receive LED pin.
    --my-leds-tx-pin=<PIN>      Transmit LED pin.
    --my-leds-blinking-inverse  Inverse the blinking feature.
    --my-signing=[none|software|password]
                                Message signing. [none]
    --my-signing-debug          Enable signing related debug.
    --my-signing-request-signatures
                                Enable signature request from nodes that in turn requested
                                gateway signature.
    --my-signing-weak_security  Enable this to permit downgrade of security preferences and
                                relaxed gateway signing requirements.
    --my-signing-whitelist=<WHITELIST>
                                If you want to use a whitelist, provide it here, make sure to avoid
                                spaces in the <whitelist> expression.
    --my-signing-verification-timeout-ms=<TIMEOUT>
                                Signing timeout. [5000]
    --my-security-password=<PASSWORD>
                                If you are using password for signing/encryption, set your password here.
EOF
}

# Colors
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
LIGHT_BLUE='\033[1;34m'
NO_COLOR='\033[0m'

OK="${GREEN}[OK]${NO_COLOR}"
ERROR="${RED}[ERROR]${NO_COLOR}"
FAILED="${YELLOW}[FAILED]${NO_COLOR}"
SECTION="${LIGHT_BLUE}[SECTION]${NO_COLOR}"

function die {
    printf "${ERROR} $1 \n"
    exit $2
}

function detect_rpi_revision {
    # get PI Revision from cpuinfo
    local pirev=$(eval "cat /proc/cpuinfo 2>/dev/null | grep Revision | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$$//'")
    echo ${pirev}
}

function detect_machine {
    local cpu=$(eval "uname -m 2>/dev/null")
    local machine=$(eval "cat /sys/firmware/devicetree/base/model 2>/dev/null |tr -d '\0'")
    local hardware=$(eval "grep sunxi_platform /sys/class/sunxi_info/sys_info 2>/dev/null | sed 's/^.*: \(.*\)$/\1/'")
    if [ -z "$hardware" ]; then
        local hardware=$(eval "grep Hardware /proc/cpuinfo 2>/dev/null | sed 's/^.*: \(.*\)$/\1/'")
    fi
    local soc="unknown"
    local tp="unknown"

    if [ -z "$cpu" ]; then
        cpu="unknown"
    fi

    case $hardware in
    BCM*)
        if [[ $machine == "Raspberry"* ]]; then
            # Calculation done by joolswills(https://github.com/joolswills) for the RetroPie-Setup project
            # and based on information from https://github.com/AndrewFromMelbourne/raspberry_pi_revision
            local rev="0x$(sed -n '/^Revision/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo)"
            # if bit 23 is not set, we are on a rpi1 (bit 23 means the revision is a bitfield)
            if [[ $((($rev >> 23) & 1)) -eq 0 ]]; then
                soc="BCM2835"
                tp="rpi1"
            else
                # if bit 23 is set, get the cpu from bits 12-15
                case "$((($rev >> 12) & 15))" in
                    0)
                        soc="BCM2835"
                        tp="rpi1"
                        ;;
                    1)
                        soc="BCM2836"
                        tp="rpi2"
                        ;;
                    2)
                        soc="BCM2837"
                        tp="rpi3"
                        ;;
                    3)
                        soc="BCM2711"
                        tp="rpi4"
                        ;;                        
                esac
            fi
        elif [[ $hardware == "BCM2708"* ]]; then
            soc="BCM2835"
        elif [[ $hardware == "BCM2709"* ]]; then
            soc="BCM2836"
        elif [[ $hardware == "BCM2710"* ]]; then
            soc="BCM2837"
        fi
        ;;
    *sun4i*|*Sun4iw1p1*)
        soc="A10"
        ;;
    *sun5i*|*Sun4iw2p1*)
        soc="A13"
        ;;
    *Sun4iw2p2*)
        soc="A12"
        ;;
    *Sun4iw2p3*)
        soc="A10s"
        ;;
    *sun6i*|*Sun8iw1p1*)
        soc="A31"
        ;;
    *Sun8iw1p2*)
        soc="A31s"
        ;;
    *sun7i*|*Sun8iw2p1*)
        soc="A20"
        if [[ $machine == "Banana Pi"* ]]; then
            tp="BananaPi"
        elif [[ $machine == "Banana Pro"* ]]; then
            tp="BananaPro"
        fi
        ;;
    *sun8i*|*Sun8iw7p1*)
        soc="H3"
        ;;
    *Sun8iw3p1*)
        soc="A23"
        ;;
    *Sun8iw5p1*)
        soc="A33"
        ;;
    *Sun8iw6p1*)
        soc="A83t"
        ;;
    *sun9i*|*Sun9iw1p1*)
        soc="A80"
        ;;
    *Sun9iw1p2*)
        soc="A80t"
        ;;
    *sun50i*|*Sun50iw1p1*)
        soc="A64"
        ;;
    'Generic AM33XX'*)
        soc="AM33XX"
        ;;
    *)
        soc="unknown"
    esac
    echo "${soc} ${tp} ${cpu}"
}

function gcc_cpu_flags {
    local soc=$1
    case $soc in
    BCM2835)
        flags="-march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard"
        ;;
    BCM2836)
        flags="-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard"
        ;;
    BCM2837)
        flags="-march=armv8-a+crc -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard"
        ;;
    BCM2711)
        flags="-march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8 -mfloat-abi=hard"
        ;;
    AM33XX)
        flags="-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard"
        ;;
    A10)
        flags="-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard"
        ;;
    A13)
        flags="-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard"
        ;;
    A20)
        flags="-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard"
        ;;
    H3)
        flags="-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard"
        ;;
    *)
        flags=""
    esac
    echo ${flags}
}

# Default values
debug=enable
gateway_type=ethernet
transport_type=rf24
signing=none
signing_request_signatures=false
encryption=false

params="SOC CFLAGS CXXFLAGS CPPFLAGS LDFLAGS PREFIX CC CXX ARDUINO_LIB_DIR BUILDDIR BINDIR GATEWAY_DIR INIT_SYSTEM SPI_DRIVER"

for opt do
    if [ "$opt" = "-h" ] || [ "$opt" = "--help" ]; then
        help
        exit 0
    fi
    optarg="${opt#*=}"
    case "$opt" in
    --spi-driver=*)
        SPI_DRIVER="$optarg"
        ;;
    --spi-spidev-device=*)
        CPPFLAGS="-DSPI_SPIDEV_DEVICE=\\\"${optarg}\\\" $CPPFLAGS"
        ;;
    --soc=*)
        SOC="$optarg"
        ;;
    --platform-type=*)
        PT="$optarg"
        ;;
    --cpu-flags=*)
        CPUFLAGS="$optarg"
        ;;
    --extra-cflags=*)
        CFLAGS="$optarg"
        ;;
    --extra-cxxflags=*)
        CXXFLAGS="$optarg $CXXFLAGS"
        ;;
    --extra-ldflags=*)
        LDFLAGS="$optarg"
        ;;
    --c_compiler=*)
        CC="$optarg"
        ;;
    --cxx_compiler=*)
        CXX="$optarg"
        ;;
    --arduino-lib-dir=*)
        ARDUINO_LIB_DIR=$optarg
        ;;
    --build-dir=*)
        BUILDDIR="$optarg"
        ;;
    --bin-dir=*)
        BINDIR="$optarg"
        ;;
    --no-clean*)
        NO_CLEAN="1"
        ;;
    --prefix=*)
        PREFIX="$optarg"
        ;;
    --exec-prefix=*)
        PREFIX="$optarg"
        ;;
    --no_init_system*)
        NO_INIT="1"
        ;;
    --gateway-dir=*)
        GATEWAY_DIR="$optarg"
        ;;
    --my-debug=*)
        debug=${optarg}
        ;;
    --my-gateway=*)
        gateway_type=${optarg}
        ;;
    --my-node-id=*)
        gateway_type="none";
        CPPFLAGS="-DMY_NODE_ID=${optarg} $CPPFLAGS"
        ;;
    --my-config-file=*)
        CPPFLAGS="-DMY_LINUX_CONFIG_FILE=\\\"${optarg}\\\" $CPPFLAGS"
        ;;
    --my-transport=*)
        transport_type=${optarg}
        ;;
    --my-serial-port=*)
        CPPFLAGS="-DMY_LINUX_SERIAL_PORT=\\\"${optarg}\\\" $CPPFLAGS"
        ;;
    --my-serial-baudrate=*)
        CPPFLAGS="-DMY_BAUD_RATE=${optarg} $CPPFLAGS"
        ;;
    --my-serial-is-pty*)
        CPPFLAGS="-DMY_LINUX_SERIAL_IS_PTY $CPPFLAGS"
        ;;
    --my-serial-pty=*)
        echo "Warning: --my-serial-pty is deprecated, please use --my-serial-port"
        CPPFLAGS="-DMY_LINUX_SERIAL_PORT=\\\"${optarg}\\\" $CPPFLAGS"
        ;;
    --my-serial-groupname=*)
        CPPFLAGS="-DMY_LINUX_SERIAL_GROUPNAME=\\\"${optarg}\\\" $CPPFLAGS"
        ;;
    --my-rf24-channel=*)
        CPPFLAGS="-DMY_RF24_CHANNEL=${optarg} $CPPFLAGS"
        ;;
    --my-rf24-pa-level=*)
        CPPFLAGS="-DMY_RF24_PA_LEVEL=${optarg} $CPPFLAGS"
        ;;
    --my-rf24-ce-pin=*)
        CPPFLAGS="-DMY_RF24_CE_PIN=${optarg} $CPPFLAGS"
        ;;
    --my-rf24-cs-pin=*)
        CPPFLAGS="-DMY_RF24_CS_PIN=${optarg} $CPPFLAGS"
        ;;
    --my-controller-url-address=*)
        CPPFLAGS="-DMY_CONTROLLER_URL_ADDRESS=\\\"${optarg}\\\" $CPPFLAGS"
        ;;
    --my-controller-ip-address=*)
        controller_ip=`echo ${optarg//./,}`
        CPPFLAGS="-DMY_CONTROLLER_IP_ADDRESS=${controller_ip} $CPPFLAGS"
        ;;
    --my-port=*)
        CPPFLAGS="-DMY_PORT=${optarg} $CPPFLAGS"
        ;;
    --my-mqtt-client-id=*)
        CPPFLAGS="-DMY_MQTT_CLIENT_ID=\\\"${optarg}\\\" $CPPFLAGS"
        ;;
    --my-mqtt-user=*)
        CPPFLAGS="-DMY_MQTT_USER=\\\"${optarg}\\\" $CPPFLAGS"
        ;;
    --my-mqtt-password=*)
        CPPFLAGS="-DMY_MQTT_PASSWORD=\\\"${optarg}\\\" $CPPFLAGS"
        ;; 
    --my-mqtt-publish-topic-prefix=*)
        CPPFLAGS="-DMY_MQTT_PUBLISH_TOPIC_PREFIX=\\\"${optarg}\\\" $CPPFLAGS"
        ;;
    --my-mqtt-subscribe-topic-prefix=*)
        CPPFLAGS="-DMY_MQTT_SUBSCRIBE_TOPIC_PREFIX=\\\"${optarg}\\\" $CPPFLAGS"
        ;;
    --my-rf24-irq-pin=*)
        CPPFLAGS="-DMY_RX_MESSAGE_BUFFER_FEATURE -DMY_RF24_IRQ_PIN=${optarg} $CPPFLAGS"
        ;;
    --my-rf24-encryption-enabled*)
        encryption=true
        CPPFLAGS="-DMY_RF24_ENABLE_ENCRYPTION $CPPFLAGS"
        ;;
    --my-rx-message-buffer-size=*)
        CPPFLAGS="-DMY_RX_MESSAGE_BUFFER_SIZE=${optarg} $CPPFLAGS"
        ;;
    --my-rfm69-frequency=*)
        if [[ ${optarg} == "315" ]]; then
            CPPFLAGS="-DMY_RFM69_FREQUENCY=RFM69_315MHZ $CPPFLAGS"
        elif [[ ${optarg} == "433" ]]; then
            CPPFLAGS="-DMY_RFM69_FREQUENCY=RFM69_433MHZ $CPPFLAGS"
        elif [[ ${optarg} == "865" ]]; then
            CPPFLAGS="-DMY_RFM69_FREQUENCY=RFM69_865MHZ $CPPFLAGS"
        elif [[ ${optarg} == "868" ]]; then
            CPPFLAGS="-DMY_RFM69_FREQUENCY=RFM69_868MHZ $CPPFLAGS"
        elif [[ ${optarg} == "915" ]]; then
            CPPFLAGS="-DMY_RFM69_FREQUENCY=RFM69_915MHZ $CPPFLAGS"
        else
            echo "[WARNING] Illegal value for --my-rfm69-frequency=${optarg}, ignored"
        fi
        ;;
    --my-is-rfm69hw*)
        CPPFLAGS="-DMY_IS_RFM69HW $CPPFLAGS"
        ;;
    --my-rfm69-irq-pin=*)
        CPPFLAGS="-DMY_RFM69_IRQ_PIN=${optarg} $CPPFLAGS"
        ;;
    --my-rfm69-cs-pin=*)
        CPPFLAGS="-DMY_RFM69_CS_PIN=${optarg} $CPPFLAGS"
        ;;
    --my-rfm69-encryption-enabled*)
        encryption=true
        CPPFLAGS="-DMY_RFM69_ENABLE_ENCRYPTION $CPPFLAGS"
        ;;
    --my-rfm95-frequency=*)
        if [[ ${optarg} == "169" ]]; then
            CPPFLAGS="-DMY_RFM95_FREQUENCY=RFM95_169MHZ $CPPFLAGS"
        elif [[ ${optarg} == "315" ]]; then
            CPPFLAGS="-DMY_RFM95_FREQUENCY=RFM95_315MHZ $CPPFLAGS"
        elif [[ ${optarg} == "434" ]]; then
            CPPFLAGS="-DMY_RFM95_FREQUENCY=RFM95_434MHZ $CPPFLAGS"
        elif [[ ${optarg} == "868" ]]; then
            CPPFLAGS="-DMY_RFM95_FREQUENCY=RFM95_868MHZ $CPPFLAGS"
        elif [[ ${optarg} == "915" ]]; then
            CPPFLAGS="-DMY_RFM95_FREQUENCY=RFM95_915MHZ $CPPFLAGS"
        else
            echo "[WARNING] Illegal value for --my-rfm95-frequency=${optarg}, ignored"
        fi
        ;;
    --my-rfm95-irq-pin=*)
        CPPFLAGS="-DMY_RFM95_IRQ_NUM=${optarg} $CPPFLAGS"
        ;;
    --my-rfm95-cs-pin=*)
        CPPFLAGS="-DMY_RFM95_CS_PIN=${optarg} $CPPFLAGS"
        ;;
    --my-rfm95-encryption-enabled*)
        encryption=true
        CPPFLAGS="-DMY_RFM95_ENABLE_ENCRYPTION $CPPFLAGS"
        ;;
    --my-rs485-serial-port=*)
        CPPFLAGS="-DMY_RS485_HWSERIAL=\\\"${optarg}\\\" $CPPFLAGS"
        ;;
    --my-rs485-baudrate=*)
        CPPFLAGS="-DMY_RS485_BAUD_RATE=${optarg} $CPPFLAGS"
        ;;
    --my-rs485-de-pin=*)
        CPPFLAGS="-DMY_RS485_DE_PIN=${optarg} $CPPFLAGS"
        ;;
    --my-rs485-max-msg-length=*)
        CPPFLAGS="-DMY_RS485_MAX_MESSAGE_LENGTH=${optarg} $CPPFLAGS"
        ;;
    --my-leds-err-pin=*)
        CPPFLAGS="-DMY_DEFAULT_ERR_LED_PIN=${optarg} $CPPFLAGS"
        ;;
    --my-leds-rx-pin=*)
        CPPFLAGS="-DMY_DEFAULT_RX_LED_PIN=${optarg} $CPPFLAGS"
        ;;
    --my-leds-tx-pin=*)
        CPPFLAGS="-DMY_DEFAULT_TX_LED_PIN=${optarg} $CPPFLAGS"
        ;;
    --my-leds-blinking-inverse*)
        CPPFLAGS="-DMY_WITH_LEDS_BLINKING_INVERSE $CPPFLAGS"
        ;;
    --my-signing=*)
        signing=${optarg}
        ;;
    --my-signing-debug*)
        CPPFLAGS="-DMY_DEBUG_VERBOSE_SIGNING $CPPFLAGS"
        ;;
    --my-signing-request-signatures*)
        signing_request_signatures=true
        ;;
    --my-signing-weak_security*)
        CPPFLAGS="-DMY_SIGNING_WEAK_SECURITY $CPPFLAGS"
        ;;
    --my-signing-whitelist*)
        CPPFLAGS="-DMY_SIGNING_NODE_WHITELISTING=${optarg} $CPPFLAGS"
        ;;
    --my-signing-verification-timeout-ms*)
        CPPFLAGS="-DMY_VERIFICATION_TIMEOUT_MS=${optarg} $CPPFLAGS"
        ;;
    --my-security-password=*)
        security_password=${optarg}
        ;;
    *)
        echo "[WARNING] Unknown option detected:$opt, ignored"
        ;;
    esac
done

PREFIX=${PREFIX:-/usr/local}
BUILDDIR=${BUILDDIR:-build}
BINDIR=${BINDIR:-bin}
GATEWAY_DIR=${GATEWAY_DIR:-${PREFIX}/bin}
CC=${CC:-gcc}
CXX=${CXX:-g++}
CXXFLAGS="$CXXFLAGS -std=c++11"

if [ -z "${SOC}" ]; then
    printf "${SECTION} Detecting target machine.\n"
    info=($(detect_machine))
    SOC=${info[0]}
    TYPE=${info[1]}
    CPU=${info[2]}
    printf "  ${OK} machine detected: SoC=${SOC}, Type=${TYPE}, CPU=${CPU}.\n"
fi

if [ -z "${CPUFLAGS}" ]; then
    CPUFLAGS=$(gcc_cpu_flags $SOC)
fi

if [[ $SOC == "BCM2835" || $SOC == "BCM2836" || $SOC == "BCM2837" || $SOC == "BCM2711" ]]; then
    CPPFLAGS="-DLINUX_ARCH_RASPBERRYPI $CPPFLAGS"
else
    printf "${SECTION} Checking GPIO Sysfs.\n"
    if [[ $(eval 'ls /sys/class/gpio/export 2>/dev/null') ]]; then
        printf "  ${OK} /sys/class/gpio/export found.\n"
    else
        echo "  [WARNING] /sys/class/gpio/export not found."
    fi
fi

if [ -z "${SPI_DRIVER}" ]; then
    printf "${SECTION} Detecting SPI driver.\n"
    if [[ $SOC == "BCM2835" || $SOC == "BCM2836" || $SOC == "BCM2837" || $SOC == "BCM2711" ]]; then
        SPI_DRIVER=BCM
    elif [[ $(eval 'ls /dev/spidev* 2>/dev/null') ]]; then
        SPI_DRIVER=SPIDEV
    fi
    if [ -n "${SPI_DRIVER}" ]; then
        printf "  ${OK} SPI driver detected:${SPI_DRIVER}.\n"
    else
        echo "  [WARNING] No supported SPI driver detected. Using SPIDEV."
        SPI_DRIVER=SPIDEV
    fi
fi
if [ -n "${SPI_DRIVER}" ]; then
    case ${SPI_DRIVER} in
        BCM)
            if [[ $SOC != "BCM2835" && $SOC != "BCM2836" && $SOC != "BCM2837" && $SOC != "BCM2711" ]]; then
                die "BCM SPI driver is only supported for SOCs BCM2835, BCM2836, BCM2837 or BCM2711" 5
            fi
            CPPFLAGS="-DLINUX_SPI_BCM $CPPFLAGS"
            ;;
        SPIDEV)
            CPPFLAGS="-DLINUX_SPI_SPIDEV $CPPFLAGS"
            ;;
        *)
            die "Unsupported SPI driver: ${SPI_DRIVER}." 1
            ;;
    esac
fi

printf "${SECTION} Gateway configuration.\n"

if [[ ${debug} == "enable" ]]; then
    CPPFLAGS="-DMY_DEBUG $CPPFLAGS"
fi

if [[ ${gateway_type} == "none" ]]; then
    # Node mode selected
    :
elif [[ ${gateway_type} == "ethernet" ]]; then
    CPPFLAGS="-DMY_GATEWAY_LINUX $CPPFLAGS"
elif [[ ${gateway_type} == "serial" ]]; then
    CPPFLAGS="-DMY_GATEWAY_SERIAL $CPPFLAGS"
elif [[ ${gateway_type} == "mqtt" ]]; then
    CPPFLAGS="-DMY_GATEWAY_LINUX -DMY_GATEWAY_MQTT_CLIENT $CPPFLAGS"
else
    die "Invalid gateway type." 2
fi
printf "  ${OK} Type: ${gateway_type}.\n"

if [[ ${transport_type} == "none" ]]; then
    # Transport disabled
    :
elif [[ ${transport_type} == "rf24" ]]; then
    CPPFLAGS="-DMY_RADIO_RF24 $CPPFLAGS"
elif [[ ${transport_type} == "rfm69" ]]; then
    CPPFLAGS="-DMY_RADIO_RFM69 -DMY_RFM69_NEW_DRIVER $CPPFLAGS"
elif [[ ${transport_type} == "rfm95" ]]; then
    CPPFLAGS="-DMY_RADIO_RFM95 $CPPFLAGS"
elif [[ ${transport_type} == "rs485" ]]; then
    CPPFLAGS="-DMY_RS485 $CPPFLAGS"
else
    die "Invalid transport type." 3
fi
printf "  ${OK} Transport: ${transport_type}.\n"

if [[ ${signing} == "none" ]]; then
    # Signing disabled
    printf "  ${OK} Signing: Disabled.\n"
elif [[ ${signing} == "software" ]]; then
    CPPFLAGS="-DMY_SIGNING_SOFT $CPPFLAGS"
    if [[ ${signing_request_signatures} == true ]]; then
        CPPFLAGS="-DMY_SIGNING_REQUEST_SIGNATURES $CPPFLAGS"
    fi
    printf "  ${OK} Signing: Enabled - Using key from config file.\n"
elif [[ ${signing} == "password" ]]; then
    if [ -z "${security_password}" ]; then
        die "You need to set the password for signing with --my-security-password option" 6
    fi
    printf "  ${OK} Signing: Enabled - Simplified signing using password.\n"
    CPPFLAGS="-DMY_SIGNING_SIMPLE_PASSWD=\\\"${security_password}\\\" $CPPFLAGS"
else
    die "Invalid signing type." 7
fi

if [[ ${encryption} == true ]]; then
    # Encryption enabled on some transport
    if [ -z "${security_password}" ]; then
        printf "  ${OK} Encryption: Enabled - Using key from config file.\n"
    else
        printf "  ${OK} Encryption: Enabled - Simplified encryption using password.\n"
        CPPFLAGS="-DMY_ENCRYPTION_SIMPLE_PASSWD=\\\"${security_password}\\\" $CPPFLAGS"
    fi
else
    printf "  ${OK} Encryption: Disabled.\n"
fi

LDFLAGS="-pthread $LDFLAGS"
CPPFLAGS="$CPUFLAGS $CPPFLAGS"

printf "  ${OK} CPPFLAGS: $CPPFLAGS\n"
printf "  ${OK} CXXFLAGS: $CXXFLAGS\n"

printf "${SECTION} Detecting init system.\n"
if [ "${NO_INIT}" ];  then
    printf "  ${OK} No init system chosen.\n"
elif [ -x /usr/bin/systemctl ] || [ -x /bin/systemctl ]; then
    INIT_SYSTEM=systemd
    printf "  ${OK} Init system detected: systemd.\n"
elif [ -f /etc/init.d/cron ] && [ ! -h /etc/init.d/cron ]; then
    INIT_SYSTEM=sysvinit
    printf "  ${OK} Init system detected: sysvinit.\n"
else
    printf "  ${FAILED} Unknown init system.\n"
fi

printf "${SECTION} Saving configuration.\n"
echo -n "" > Makefile.inc
for param in ${params}; do
    if [[ ${!param} ]]; then
        echo "${param}=${!param}" >> Makefile.inc
    fi
done
printf "  ${OK} Saved.\n"

if [ -z "${NO_CLEAN}" ]; then
    printf "${SECTION} Cleaning previous builds.\n"
    make clean >/dev/null
fi


printf "  ${OK} Finished.\n"
