diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml
index 693a2284d..5f931270c 100644
--- a/.trunk/trunk.yaml
+++ b/.trunk/trunk.yaml
@@ -8,15 +8,15 @@ plugins:
uri: https://github.com/trunk-io/plugins
lint:
enabled:
- - checkov@3.2.436
- - renovate@40.41.0
+ - checkov@3.2.440
+ - renovate@40.49.10
- prettier@3.5.3
- - trufflehog@3.88.35
+ - trufflehog@3.89.1
- yamllint@1.37.1
- bandit@1.8.3
- trivy@0.63.0
- taplo@0.9.3
- - ruff@0.11.12
+ - ruff@0.11.13
- isort@6.0.1
- markdownlint@0.45.0
- oxipng@9.1.5
@@ -28,7 +28,7 @@ lint:
- shellcheck@0.10.0
- black@25.1.0
- git-diff-check
- - gitleaks@8.27.0
+ - gitleaks@8.27.2
- clang-format@16.0.3
ignore:
- linters: [ALL]
diff --git a/alpine.Dockerfile b/alpine.Dockerfile
index bf7cad6d4..670736241 100644
--- a/alpine.Dockerfile
+++ b/alpine.Dockerfile
@@ -3,7 +3,7 @@
# trunk-ignore-all(hadolint/DL3018): Do not pin apk package versions
# trunk-ignore-all(hadolint/DL3013): Do not pin pip package versions
-FROM python:3.13-alpine3.21 AS builder
+FROM python:3.13-alpine3.22 AS builder
ARG PIO_ENV=native
ENV PIP_ROOT_USER_ACTION=ignore
@@ -27,7 +27,7 @@ RUN bash ./bin/build-native.sh "$PIO_ENV" && \
# ##### PRODUCTION BUILD #############
-FROM alpine:3.21
+FROM alpine:3.22
LABEL org.opencontainers.image.title="Meshtastic" \
org.opencontainers.image.description="Alpine Meshtastic daemon" \
org.opencontainers.image.url="https://meshtastic.org" \
diff --git a/arch/esp32/esp32.ini b/arch/esp32/esp32.ini
index a6eff7bf9..cba84181b 100644
--- a/arch/esp32/esp32.ini
+++ b/arch/esp32/esp32.ini
@@ -4,7 +4,7 @@ extends = arduino_base
custom_esp32_kind = esp32
platform =
# renovate: datasource=custom.pio depName=platformio/espressif32 packageName=platformio/platform/espressif32
- platformio/espressif32@6.10.0
+ platformio/espressif32@6.11.0
build_src_filter =
${arduino_base.build_src_filter} - - - - -
diff --git a/arch/portduino/portduino.ini b/arch/portduino/portduino.ini
index a19c50319..429e010f5 100644
--- a/arch/portduino/portduino.ini
+++ b/arch/portduino/portduino.ini
@@ -2,7 +2,7 @@
[portduino_base]
platform =
# renovate: datasource=git-refs depName=platform-native packageName=https://github.com/meshtastic/platform-native gitBranch=develop
- https://github.com/meshtastic/platform-native/archive/622341c6de8a239704318b10c3dbb00c21a3eab3.zip
+ https://github.com/meshtastic/platform-native/archive/681ee029207e9fd040afa223df6e54074cbbe084.zip
framework = arduino
build_src_filter =
diff --git a/arch/stm32/stm32.ini b/arch/stm32/stm32.ini
index dd190c9d4..e7a340f92 100644
--- a/arch/stm32/stm32.ini
+++ b/arch/stm32/stm32.ini
@@ -2,7 +2,7 @@
extends = arduino_base
platform =
# renovate: datasource=custom.pio depName=platformio/ststm32 packageName=platformio/platform/ststm32
- platformio/ststm32@19.1.0
+ platformio/ststm32@19.2.0
platform_packages =
# TODO renovate
platformio/framework-arduinoststm32@https://github.com/stm32duino/Arduino_Core_STM32/archive/2.10.1.zip
diff --git a/bin/config.d/lora-lyra-picocalc-wio-sx1262.yaml b/bin/config.d/lora-lyra-picocalc-wio-sx1262.yaml
new file mode 100644
index 000000000..2fd128ce8
--- /dev/null
+++ b/bin/config.d/lora-lyra-picocalc-wio-sx1262.yaml
@@ -0,0 +1,18 @@
+Lora:
+ Module: sx1262
+ DIO2_AS_RF_SWITCH: true
+ DIO3_TCXO_VOLTAGE: true
+ gpiochip: 0
+ MOSI: 12
+ MISO: 13
+ IRQ: 1
+ Busy: 23
+ Reset: 22
+ RXen: 0
+ gpiochip: 1
+ CS: 9
+ SCK: 11
+# TXen: bridge to DIO2 on E22 module
+ SX126X_MAX_POWER: 22
+ spidev: spidev1.0
+ spiSpeed: 2000000
diff --git a/bin/device-install.sh b/bin/device-install.sh
index 76765bb5f..613696d2f 100755
--- a/bin/device-install.sh
+++ b/bin/device-install.sh
@@ -33,47 +33,50 @@ BIGDB_16MB=(
"ESP32-S3-Pico"
"m5stack-cores3"
"station-g2"
- "t-eth-elite"
- "t-watch-s3"
+ "t-eth-elite"
+ "t-watch-s3"
+ "elecrow-adv-35-tft"
+ "elecrow-adv-24-28-tft"
+ "elecrow-adv1-43-50-70-tft"
)
S3_VARIANTS=(
- "s3"
- "-v3"
- "t-deck"
- "wireless-paper"
- "wireless-tracker"
- "station-g2"
- "unphone"
- "t-eth-elite"
- "mesh-tab"
- "dreamcatcher"
- "ESP32-S3-Pico"
- "seeed-sensecap-indicator"
- "heltec_capsule_sensor_v3"
- "vision-master"
- "icarus"
- "tracksenger"
- "elecrow-adv"
+ "s3"
+ "-v3"
+ "t-deck"
+ "wireless-paper"
+ "wireless-tracker"
+ "station-g2"
+ "unphone"
+ "t-eth-elite"
+ "mesh-tab"
+ "dreamcatcher"
+ "ESP32-S3-Pico"
+ "seeed-sensecap-indicator"
+ "heltec_capsule_sensor_v3"
+ "vision-master"
+ "icarus"
+ "tracksenger"
+ "elecrow-adv"
)
# Determine the correct esptool command to use
if "$PYTHON" -m esptool version >/dev/null 2>&1; then
- ESPTOOL_CMD="$PYTHON -m esptool"
+ ESPTOOL_CMD="$PYTHON -m esptool"
elif command -v esptool >/dev/null 2>&1; then
- ESPTOOL_CMD="esptool"
+ ESPTOOL_CMD="esptool"
elif command -v esptool.py >/dev/null 2>&1; then
- ESPTOOL_CMD="esptool.py"
+ ESPTOOL_CMD="esptool.py"
else
- echo "Error: esptool not found"
- exit 1
+ echo "Error: esptool not found"
+ exit 1
fi
set -e
# Usage info
show_help() {
- cat <&2
- exit 1
- ;;
- esac
- shift # Move to the next argument
+ case "$1" in
+ -h | --help)
+ show_help
+ exit 0
+ ;;
+ -p)
+ ESPTOOL_CMD="$ESPTOOL_CMD --port $2"
+ shift
+ ;;
+ -P)
+ PYTHON="$2"
+ shift
+ ;;
+ -f)
+ FILENAME="$2"
+ shift
+ ;;
+ --web)
+ WEB_APP=true
+ ;;
+ --1200bps-reset)
+ BPS_RESET=true
+ ;;
+ --) # Stop parsing options
+ shift
+ break
+ ;;
+ *)
+ echo "Unknown argument: $1" >&2
+ exit 1
+ ;;
+ esac
+ shift # Move to the next argument
done
if [[ $BPS_RESET == true ]]; then
@@ -127,100 +130,100 @@ if [[ $BPS_RESET == true ]]; then
exit 0
fi
-[ -z "$FILENAME" -a -n "$1" ] && {
- FILENAME=$1
- shift
+[ -z "$FILENAME" ] && [ -n "$1" ] && {
+ FILENAME="$1"
+ shift
}
-if [[ $FILENAME != firmware-* ]]; then
+if [[ "$FILENAME" != firmware-* ]]; then
echo "Filename must be a firmware-* file."
exit 1
fi
# Check if FILENAME contains "-tft-" and prevent web/mui comingling.
-if [[ ${FILENAME//-tft-/} != "$FILENAME" ]]; then
- TFT_BUILD=true
- if [[ $WEB_APP == true ]] && [[ $TFT_BUILD == true ]]; then
- echo "Cannot enable WebUI (--web) and MUI."
- exit 1
- fi
+if [[ "${FILENAME//-tft-/}" != "$FILENAME" ]]; then
+ TFT_BUILD=true
+ if [[ $WEB_APP == true ]] && [[ $TFT_BUILD == true ]]; then
+ echo "Cannot enable WebUI (--web) and MUI."
+ exit 1
+ fi
fi
# Extract BASENAME from %FILENAME% for later use.
BASENAME="${FILENAME/firmware-/}"
if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then
- # Default littlefs* offset (--web).
- OFFSET=0x300000
+ # Default littlefs* offset (--web).
+ OFFSET=0x300000
- # Default OTA Offset
- OTA_OFFSET=0x260000
+ # Default OTA Offset
+ OTA_OFFSET=0x260000
- # littlefs* offset for BigDB 8mb and OTA OFFSET.
- for variant in "${BIGDB_8MB[@]}"; do
- if [ -z "${FILENAME##*"$variant"*}" ]; then
- OFFSET=0x670000
- OTA_OFFSET=0x340000
- fi
- done
+ # littlefs* offset for BigDB 8mb and OTA OFFSET.
+ for variant in "${BIGDB_8MB[@]}"; do
+ if [ -z "${FILENAME##*"$variant"*}" ]; then
+ OFFSET=0x670000
+ OTA_OFFSET=0x340000
+ fi
+ done
- # littlefs* offset for BigDB 16mb and OTA OFFSET.
- for variant in "${BIGDB_16MB[@]}"; do
- if [ -z "${FILENAME##*"$variant"*}" ]; then
- OFFSET=0xc90000
- OTA_OFFSET=0x650000
- fi
- done
+ # littlefs* offset for BigDB 16mb and OTA OFFSET.
+ for variant in "${BIGDB_16MB[@]}"; do
+ if [ -z "${FILENAME##*"$variant"*}" ]; then
+ OFFSET=0xc90000
+ OTA_OFFSET=0x650000
+ fi
+ done
- # Account for S3 board's different OTA partition
- # FIXME: Use PlatformIO info to determine MCU type, this is unmaintainable
- for variant in "${S3_VARIANTS[@]}"; do
- if [ -z "${FILENAME##*"$variant"*}" ]; then
- MCU="esp32s3"
- fi
- done
+ # Account for S3 board's different OTA partition
+ # FIXME: Use PlatformIO info to determine MCU type, this is unmaintainable
+ for variant in "${S3_VARIANTS[@]}"; do
+ if [ -z "${FILENAME##*"$variant"*}" ]; then
+ MCU="esp32s3"
+ fi
+ done
- if [ "$MCU" != "esp32s3" ]; then
- if [ -n "${FILENAME##*"esp32c3"*}" ]; then
- OTAFILE=bleota.bin
- else
- OTAFILE=bleota-c3.bin
- fi
- else
- OTAFILE=bleota-s3.bin
- fi
+ if [ "$MCU" != "esp32s3" ]; then
+ if [ -n "${FILENAME##*"esp32c3"*}" ]; then
+ OTAFILE=bleota.bin
+ else
+ OTAFILE=bleota-c3.bin
+ fi
+ else
+ OTAFILE=bleota-s3.bin
+ fi
- # Check if WEB_APP (--web) is enabled and add "littlefswebui-" to BASENAME else "littlefs-".
- if [ "$WEB_APP" = true ]; then
- SPIFFSFILE=littlefswebui-${BASENAME}
- else
- SPIFFSFILE=littlefs-${BASENAME}
- fi
+ # Check if WEB_APP (--web) is enabled and add "littlefswebui-" to BASENAME else "littlefs-".
+ if [ "$WEB_APP" = true ]; then
+ SPIFFSFILE=littlefswebui-${BASENAME}
+ else
+ SPIFFSFILE=littlefs-${BASENAME}
+ fi
- if [[ ! -f $FILENAME ]]; then
- echo "Error: file ${FILENAME} wasn't found. Terminating."
- exit 1
- fi
- if [[ ! -f $OTAFILE ]]; then
- echo "Error: file ${OTAFILE} wasn't found. Terminating."
- exit 1
- fi
- if [[ ! -f $SPIFFSFILE ]]; then
- echo "Error: file ${SPIFFSFILE} wasn't found. Terminating."
- exit 1
- fi
+ if [[ ! -f "$FILENAME" ]]; then
+ echo "Error: file ${FILENAME} wasn't found. Terminating."
+ exit 1
+ fi
+ if [[ ! -f "$OTAFILE" ]]; then
+ echo "Error: file ${OTAFILE} wasn't found. Terminating."
+ exit 1
+ fi
+ if [[ ! -f "$SPIFFSFILE" ]]; then
+ echo "Error: file ${SPIFFSFILE} wasn't found. Terminating."
+ exit 1
+ fi
- echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
- $ESPTOOL_CMD erase_flash
- $ESPTOOL_CMD write_flash 0x00 "${FILENAME}"
- echo "Trying to flash ${OTAFILE} at offset ${OTA_OFFSET}"
- $ESPTOOL_CMD write_flash $OTA_OFFSET "${OTAFILE}"
- echo "Trying to flash ${SPIFFSFILE}, at offset ${OFFSET}"
- $ESPTOOL_CMD write_flash $OFFSET "${SPIFFSFILE}"
+ echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
+ $ESPTOOL_CMD erase_flash
+ $ESPTOOL_CMD write_flash 0x00 "${FILENAME}"
+ echo "Trying to flash ${OTAFILE} at offset ${OTA_OFFSET}"
+ $ESPTOOL_CMD write_flash $OTA_OFFSET "${OTAFILE}"
+ echo "Trying to flash ${SPIFFSFILE}, at offset ${OFFSET}"
+ $ESPTOOL_CMD write_flash $OFFSET "${SPIFFSFILE}"
else
- show_help
- echo "Invalid file: ${FILENAME}"
+ show_help
+ echo "Invalid file: ${FILENAME}"
fi
exit 0
diff --git a/bin/device-update.sh b/bin/device-update.sh
index c32b953e6..6adfe4e0e 100755
--- a/bin/device-update.sh
+++ b/bin/device-update.sh
@@ -18,8 +18,8 @@ fi
# Usage info
show_help() {
cat << EOF
-Usage: $(basename $0) [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME|FILENAME] [--change-mode]
-Flash image file to device, leave existing system intact.
+Usage: $(basename "$0") [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME|FILENAME] [--change-mode]
+Flash image file to device, leave existing system intact."
-h Display this help and exit
-p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerous).
@@ -38,7 +38,7 @@ while getopts ":hp:P:f:" opt; do
exit 0
;;
p) ESPTOOL_CMD="$ESPTOOL_CMD --port ${OPTARG}"
- ;;
+ ;;
P) PYTHON=${OPTARG}
;;
f) FILENAME=${OPTARG}
@@ -47,7 +47,7 @@ while getopts ":hp:P:f:" opt; do
CHANGE_MODE=true
;;
*)
- echo "Invalid flag."
+ echo "Invalid flag."
show_help >&2
exit 1
;;
@@ -60,17 +60,17 @@ if [[ $CHANGE_MODE == true ]]; then
exit 0
fi
-[ -z "$FILENAME" -a -n "$1" ] && {
- FILENAME=$1
+[ -z "$FILENAME" ] && [ -n "$1" ] && {
+ FILENAME="$1"
shift
}
if [ -f "${FILENAME}" ] && [ -z "${FILENAME##*"update"*}" ]; then
- printf "Trying to flash update ${FILENAME}"
- $ESPTOOL_CMD --baud 115200 write_flash 0x10000 ${FILENAME}
+ echo "Trying to flash update ${FILENAME}"
+ $ESPTOOL_CMD --baud 115200 write_flash 0x10000 "${FILENAME}"
else
- show_help
- echo "Invalid file: ${FILENAME}"
+ show_help
+ echo "Invalid file: ${FILENAME}"
fi
exit 0
diff --git a/bin/generate_ci_matrix.py b/bin/generate_ci_matrix.py
index 7513ccff5..0ce6b0f6b 100755
--- a/bin/generate_ci_matrix.py
+++ b/bin/generate_ci_matrix.py
@@ -27,7 +27,7 @@ for subdir, dirs, files in os.walk(rootdir):
if c.startswith("env:"):
section = config[c].name[4:]
if "extends" in config[config[c].name]:
- if config[config[c].name]["extends"] == options[0] + "_base":
+ if options[0] + "_base" in config[config[c].name]["extends"]:
if "board_level" in config[config[c].name]:
if (
config[config[c].name]["board_level"] == "extra"
diff --git a/bin/web.version b/bin/web.version
index e46a05b19..a4db534a2 100644
--- a/bin/web.version
+++ b/bin/web.version
@@ -1 +1 @@
-2.6.4
\ No newline at end of file
+2.5.3
\ No newline at end of file
diff --git a/boards/ThinkNode-M1.json b/boards/ThinkNode-M1.json
index e55da3ec7..2d6dbc352 100644
--- a/boards/ThinkNode-M1.json
+++ b/boards/ThinkNode-M1.json
@@ -48,6 +48,6 @@
"require_upload_port": true,
"wait_for_upload_port": true
},
- "url": "FIXME",
+ "url": "https://www.elecrow.com/thinknode-m1-meshtastic-lora-signal-transceiver-powered-by-nrf52840-with-154-screen-support-gps.html",
"vendor": "ELECROW"
}
diff --git a/boards/heltec_mesh_node_t114.json b/boards/heltec_mesh_node_t114.json
index 2bd306eb9..d516c9701 100644
--- a/boards/heltec_mesh_node_t114.json
+++ b/boards/heltec_mesh_node_t114.json
@@ -48,6 +48,6 @@
"require_upload_port": true,
"wait_for_upload_port": true
},
- "url": "FIXME",
+ "url": "https://heltec.org/project/mesh-node-t114/",
"vendor": "Heltec"
}
diff --git a/platformio.ini b/platformio.ini
index ecde59de2..555879fb5 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -108,7 +108,7 @@ lib_deps =
[device-ui_base]
lib_deps =
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
- https://github.com/meshtastic/device-ui/archive/649e0953508ee4aabf1171519ee2eb69fb125647.zip
+ https://github.com/meshtastic/device-ui/archive/1b520fcb168c7447a8d6a6ebc56954c9f472e964.zip
; Common libs for environmental measurements in telemetry module
[environmental_base]
diff --git a/protobufs b/protobufs
index 24c7a3d28..0c112881d 160000
--- a/protobufs
+++ b/protobufs
@@ -1 +1 @@
-Subproject commit 24c7a3d287a4bd269ce191827e5dabd8ce8f57a7
+Subproject commit 0c112881dfb4aa24a61ee55dd4c46abbfc093717
diff --git a/src/AmbientLightingThread.h b/src/AmbientLightingThread.h
index bff8846d6..e4ef3b443 100644
--- a/src/AmbientLightingThread.h
+++ b/src/AmbientLightingThread.h
@@ -59,82 +59,82 @@ class AmbientLightingThread : public concurrency::OSThread
return;
}
LOG_DEBUG("AmbientLighting init");
-#if defined(HAS_NCP5623) || defined(HAS_LP5562)
+#ifdef HAS_NCP5623
if (_type == ScanI2C::NCP5623) {
rgb.begin();
#endif
#ifdef HAS_LP5562
- } else if (_type == ScanI2C::LP5562) {
- rgbw.begin();
+ if (_type == ScanI2C::LP5562) {
+ rgbw.begin();
#endif
#ifdef RGBLED_RED
- pinMode(RGBLED_RED, OUTPUT);
- pinMode(RGBLED_GREEN, OUTPUT);
- pinMode(RGBLED_BLUE, OUTPUT);
+ pinMode(RGBLED_RED, OUTPUT);
+ pinMode(RGBLED_GREEN, OUTPUT);
+ pinMode(RGBLED_BLUE, OUTPUT);
#endif
#ifdef HAS_NEOPIXEL
- pixels.begin(); // Initialise the pixel(s)
- pixels.clear(); // Set all pixel colors to 'off'
- pixels.setBrightness(moduleConfig.ambient_lighting.current);
+ pixels.begin(); // Initialise the pixel(s)
+ pixels.clear(); // Set all pixel colors to 'off'
+ pixels.setBrightness(moduleConfig.ambient_lighting.current);
#endif
- setLighting();
+ setLighting();
#endif
#if defined(HAS_NCP5623) || defined(HAS_LP5562)
- }
+ }
#endif
- }
+ }
- protected:
- int32_t runOnce() override
- {
+ protected:
+ int32_t runOnce() override
+ {
#ifdef HAS_RGB_LED
#if defined(HAS_NCP5623) || defined(HAS_LP5562)
- if ((_type == ScanI2C::NCP5623 || _type == ScanI2C::LP5562) && moduleConfig.ambient_lighting.led_state) {
+ if ((_type == ScanI2C::NCP5623 || _type == ScanI2C::LP5562) && moduleConfig.ambient_lighting.led_state) {
#endif
- setLighting();
- return 30000; // 30 seconds to reset from any animations that may have been running from Ext. Notification
+ setLighting();
+ return 30000; // 30 seconds to reset from any animations that may have been running from Ext. Notification
#if defined(HAS_NCP5623) || defined(HAS_LP5562)
+ }
+#endif
+#endif
+ return disable();
}
-#endif
-#endif
- return disable();
- }
- // When shutdown() is issued, setLightingOff will be called.
- CallbackObserver notifyDeepSleepObserver =
- CallbackObserver(this, &AmbientLightingThread::setLightingOff);
+ // When shutdown() is issued, setLightingOff will be called.
+ CallbackObserver notifyDeepSleepObserver =
+ CallbackObserver(this, &AmbientLightingThread::setLightingOff);
- private:
- ScanI2C::DeviceType _type = ScanI2C::DeviceType::NONE;
+ private:
+ ScanI2C::DeviceType _type = ScanI2C::DeviceType::NONE;
- // Turn RGB lighting off, is used in junction to shutdown()
- int setLightingOff(void *unused)
- {
+ // Turn RGB lighting off, is used in junction to shutdown()
+ int setLightingOff(void *unused)
+ {
#ifdef HAS_NCP5623
- rgb.setCurrent(0);
- rgb.setRed(0);
- rgb.setGreen(0);
- rgb.setBlue(0);
- LOG_INFO("OFF: NCP5623 Ambient lighting");
+ rgb.setCurrent(0);
+ rgb.setRed(0);
+ rgb.setGreen(0);
+ rgb.setBlue(0);
+ LOG_INFO("OFF: NCP5623 Ambient lighting");
#endif
#ifdef HAS_LP5562
- rgbw.setCurrent(0);
- rgbw.setRed(0);
- rgbw.setGreen(0);
- rgbw.setBlue(0);
- rgbw.setWhite(0);
- LOG_INFO("OFF: LP5562 Ambient lighting");
+ rgbw.setCurrent(0);
+ rgbw.setRed(0);
+ rgbw.setGreen(0);
+ rgbw.setBlue(0);
+ rgbw.setWhite(0);
+ LOG_INFO("OFF: LP5562 Ambient lighting");
#endif
#ifdef HAS_NEOPIXEL
- pixels.clear();
- pixels.show();
- LOG_INFO("OFF: NeoPixel Ambient lighting");
+ pixels.clear();
+ pixels.show();
+ LOG_INFO("OFF: NeoPixel Ambient lighting");
#endif
#ifdef RGBLED_CA
- analogWrite(RGBLED_RED, 255 - 0);
- analogWrite(RGBLED_GREEN, 255 - 0);
- analogWrite(RGBLED_BLUE, 255 - 0);
- LOG_INFO("OFF: Ambient light RGB Common Anode");
+ analogWrite(RGBLED_RED, 255 - 0);
+ analogWrite(RGBLED_GREEN, 255 - 0);
+ analogWrite(RGBLED_BLUE, 255 - 0);
+ LOG_INFO("OFF: Ambient light RGB Common Anode");
#elif defined(RGBLED_RED)
analogWrite(RGBLED_RED, 0);
analogWrite(RGBLED_GREEN, 0);
@@ -142,56 +142,57 @@ class AmbientLightingThread : public concurrency::OSThread
LOG_INFO("OFF: Ambient light RGB Common Cathode");
#endif
#ifdef UNPHONE
- unphone.rgb(0, 0, 0);
- LOG_INFO("OFF: unPhone Ambient lighting");
+ unphone.rgb(0, 0, 0);
+ LOG_INFO("OFF: unPhone Ambient lighting");
#endif
- return 0;
- }
+ return 0;
+ }
- void setLighting()
- {
+ void setLighting()
+ {
#ifdef HAS_NCP5623
- rgb.setCurrent(moduleConfig.ambient_lighting.current);
- rgb.setRed(moduleConfig.ambient_lighting.red);
- rgb.setGreen(moduleConfig.ambient_lighting.green);
- rgb.setBlue(moduleConfig.ambient_lighting.blue);
- LOG_DEBUG("Init NCP5623 Ambient light w/ current=%d, red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.current,
- moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
+ rgb.setCurrent(moduleConfig.ambient_lighting.current);
+ rgb.setRed(moduleConfig.ambient_lighting.red);
+ rgb.setGreen(moduleConfig.ambient_lighting.green);
+ rgb.setBlue(moduleConfig.ambient_lighting.blue);
+ LOG_DEBUG("Init NCP5623 Ambient light w/ current=%d, red=%d, green=%d, blue=%d",
+ moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red,
+ moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
#endif
#ifdef HAS_LP5562
- rgbw.setCurrent(moduleConfig.ambient_lighting.current);
- rgbw.setRed(moduleConfig.ambient_lighting.red);
- rgbw.setGreen(moduleConfig.ambient_lighting.green);
- rgbw.setBlue(moduleConfig.ambient_lighting.blue);
- LOG_DEBUG("Init LP5562 Ambient light w/ current=%d, red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.current,
- moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
+ rgbw.setCurrent(moduleConfig.ambient_lighting.current);
+ rgbw.setRed(moduleConfig.ambient_lighting.red);
+ rgbw.setGreen(moduleConfig.ambient_lighting.green);
+ rgbw.setBlue(moduleConfig.ambient_lighting.blue);
+ LOG_DEBUG("Init LP5562 Ambient light w/ current=%d, red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.current,
+ moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
#endif
#ifdef HAS_NEOPIXEL
- pixels.fill(pixels.Color(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
- moduleConfig.ambient_lighting.blue),
- 0, NEOPIXEL_COUNT);
+ pixels.fill(pixels.Color(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
+ moduleConfig.ambient_lighting.blue),
+ 0, NEOPIXEL_COUNT);
// RadioMaster Bandit has addressable LED at the two buttons
// this allow us to set different lighting for them in variant.h file.
#ifdef RADIOMASTER_900_BANDIT
#if defined(BUTTON1_COLOR) && defined(BUTTON1_COLOR_INDEX)
- pixels.fill(BUTTON1_COLOR, BUTTON1_COLOR_INDEX, 1);
+ pixels.fill(BUTTON1_COLOR, BUTTON1_COLOR_INDEX, 1);
#endif
#if defined(BUTTON2_COLOR) && defined(BUTTON2_COLOR_INDEX)
- pixels.fill(BUTTON2_COLOR, BUTTON2_COLOR_INDEX, 1);
+ pixels.fill(BUTTON2_COLOR, BUTTON2_COLOR_INDEX, 1);
#endif
#endif
- pixels.show();
- LOG_DEBUG("Init NeoPixel Ambient light w/ brightness(current)=%d, red=%d, green=%d, blue=%d",
- moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
- moduleConfig.ambient_lighting.blue);
+ pixels.show();
+ LOG_DEBUG("Init NeoPixel Ambient light w/ brightness(current)=%d, red=%d, green=%d, blue=%d",
+ moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red,
+ moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
#endif
#ifdef RGBLED_CA
- analogWrite(RGBLED_RED, 255 - moduleConfig.ambient_lighting.red);
- analogWrite(RGBLED_GREEN, 255 - moduleConfig.ambient_lighting.green);
- analogWrite(RGBLED_BLUE, 255 - moduleConfig.ambient_lighting.blue);
- LOG_DEBUG("Init Ambient light RGB Common Anode w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red,
- moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
+ analogWrite(RGBLED_RED, 255 - moduleConfig.ambient_lighting.red);
+ analogWrite(RGBLED_GREEN, 255 - moduleConfig.ambient_lighting.green);
+ analogWrite(RGBLED_BLUE, 255 - moduleConfig.ambient_lighting.blue);
+ LOG_DEBUG("Init Ambient light RGB Common Anode w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red,
+ moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
#elif defined(RGBLED_RED)
analogWrite(RGBLED_RED, moduleConfig.ambient_lighting.red);
analogWrite(RGBLED_GREEN, moduleConfig.ambient_lighting.green);
@@ -200,11 +201,12 @@ class AmbientLightingThread : public concurrency::OSThread
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
#endif
#ifdef UNPHONE
- unphone.rgb(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
- LOG_DEBUG("Init unPhone Ambient light w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red,
- moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
+ unphone.rgb(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
+ moduleConfig.ambient_lighting.blue);
+ LOG_DEBUG("Init unPhone Ambient light w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red,
+ moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
#endif
- }
-};
+ }
+ };
} // namespace concurrency
diff --git a/src/BluetoothStatus.h b/src/BluetoothStatus.h
index 526b6f243..f6bb43cc2 100644
--- a/src/BluetoothStatus.h
+++ b/src/BluetoothStatus.h
@@ -88,10 +88,16 @@ class BluetoothStatus : public Status
break;
case ConnectionState::CONNECTED:
LOG_DEBUG("BluetoothStatus CONNECTED");
+#ifdef BLE_LED
+ digitalWrite(BLE_LED, HIGH);
+#endif
break;
case ConnectionState::DISCONNECTED:
LOG_DEBUG("BluetoothStatus DISCONNECTED");
+#ifdef BLE_LED
+ digitalWrite(BLE_LED, LOW);
+#endif
break;
}
}
@@ -102,4 +108,4 @@ class BluetoothStatus : public Status
} // namespace meshtastic
-extern meshtastic::BluetoothStatus *bluetoothStatus;
\ No newline at end of file
+extern meshtastic::BluetoothStatus *bluetoothStatus;
diff --git a/src/concurrency/Lock.cpp b/src/concurrency/Lock.cpp
index 11501359b..0fe80e455 100644
--- a/src/concurrency/Lock.cpp
+++ b/src/concurrency/Lock.cpp
@@ -9,17 +9,23 @@ namespace concurrency
Lock::Lock() : handle(xSemaphoreCreateBinary())
{
assert(handle);
- assert(xSemaphoreGive(handle));
+ if (xSemaphoreGive(handle) == false) {
+ abort();
+ }
}
void Lock::lock()
{
- assert(xSemaphoreTake(handle, portMAX_DELAY));
+ if (xSemaphoreTake(handle, portMAX_DELAY) == false) {
+ abort();
+ }
}
void Lock::unlock()
{
- assert(xSemaphoreGive(handle));
+ if (xSemaphoreGive(handle) == false) {
+ abort();
+ }
}
#else
Lock::Lock() {}
diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp
index 14787baff..76fe6b2d3 100644
--- a/src/graphics/TFTDisplay.cpp
+++ b/src/graphics/TFTDisplay.cpp
@@ -467,18 +467,27 @@ class LGFX : public lgfx::LGFX_Device
// The following setting values are general initial values for each panel, so please comment out any
// unknown items and try them.
-
- cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC
- cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC
- cfg.panel_width = TFT_WIDTH; // actual displayable width
- cfg.panel_height = TFT_HEIGHT; // actual displayable height
- cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction
- cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction
- cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is mirrored)
+#if defined(T_WATCH_S3)
+ cfg.panel_width = 240;
+ cfg.panel_height = 240;
+ cfg.memory_width = 240;
+ cfg.memory_height = 320;
+ cfg.offset_x = 0;
+ cfg.offset_y = 0; // No vertical shift needed — panel is top-aligned
+ cfg.offset_rotation = 2; // Rotate 180° to correct upside-down layout
+#else
+ cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC
+ cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC
+ cfg.panel_width = TFT_WIDTH; // actual displayable width
+ cfg.panel_height = TFT_HEIGHT; // actual displayable height
+ cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction
+ cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction
+ cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is mirrored)
+#endif
#ifdef TFT_DUMMY_READ_PIXELS
cfg.dummy_read_pixel = TFT_DUMMY_READ_PIXELS; // Number of bits for dummy read before pixel readout
#else
- cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout
+ cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout
#endif
cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read
cfg.readable = true; // Set to true if data can be read
diff --git a/src/graphics/niche/Drivers/EInk/GDEY0154D67.cpp b/src/graphics/niche/Drivers/EInk/GDEY0154D67.cpp
index 2cab179b9..9a06fa841 100644
--- a/src/graphics/niche/Drivers/EInk/GDEY0154D67.cpp
+++ b/src/graphics/niche/Drivers/EInk/GDEY0154D67.cpp
@@ -9,12 +9,9 @@ void GDEY0154D67::configScanning()
{
// "Driver output control"
sendCommand(0x01);
- sendData(0xC7);
+ sendData(0xC7); // Scan until gate 199 (200px vertical res.)
sendData(0x00);
sendData(0x00);
-
- // To-do: delete this method?
- // Values set here might be redundant: C7, 00, 00 seems to be default
}
// Specify which information is used to control the sequence of voltages applied to move the pixels
@@ -52,10 +49,10 @@ void GDEY0154D67::detachFromUpdate()
{
switch (updateType) {
case FAST:
- return beginPolling(50, 500); // At least 500ms for fast refresh
+ return beginPolling(50, 300); // At least 300ms for fast refresh
case FULL:
default:
- return beginPolling(100, 2000); // At least 2 seconds for full refresh
+ return beginPolling(100, 1500); // At least 1.5 seconds for full refresh
}
}
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
\ No newline at end of file
diff --git a/src/graphics/niche/Drivers/EInk/GDEY0154D67.h b/src/graphics/niche/Drivers/EInk/GDEY0154D67.h
index 93c641e44..e391eea50 100644
--- a/src/graphics/niche/Drivers/EInk/GDEY0154D67.h
+++ b/src/graphics/niche/Drivers/EInk/GDEY0154D67.h
@@ -31,9 +31,9 @@ class GDEY0154D67 : public SSD16XX
GDEY0154D67() : SSD16XX(width, height, supported) {}
protected:
- virtual void configScanning() override;
- virtual void configWaveform() override;
- virtual void configUpdateSequence() override;
+ void configScanning() override;
+ void configWaveform() override;
+ void configUpdateSequence() override;
void detachFromUpdate() override;
};
diff --git a/src/graphics/niche/Drivers/EInk/GDEY0213B74.cpp b/src/graphics/niche/Drivers/EInk/GDEY0213B74.cpp
index a0ff63258..b3a585eb7 100644
--- a/src/graphics/niche/Drivers/EInk/GDEY0213B74.cpp
+++ b/src/graphics/niche/Drivers/EInk/GDEY0213B74.cpp
@@ -12,9 +12,6 @@ void GDEY0213B74::configScanning()
sendData(0xF9);
sendData(0x00);
sendData(0x00);
-
- // To-do: delete this method?
- // Values set here might be redundant: F9, 00, 00 seems to be default
}
// Specify which information is used to control the sequence of voltages applied to move the pixels
diff --git a/src/graphics/niche/Drivers/EInk/HINK_E0213A289.cpp b/src/graphics/niche/Drivers/EInk/HINK_E0213A289.cpp
new file mode 100644
index 000000000..0509b0502
--- /dev/null
+++ b/src/graphics/niche/Drivers/EInk/HINK_E0213A289.cpp
@@ -0,0 +1,61 @@
+#include "./HINK_E0213A289.h"
+
+#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
+
+using namespace NicheGraphics::Drivers;
+
+// Map the display controller IC's output to the connected panel
+void HINK_E0213A289::configScanning()
+{
+ // "Driver output control"
+ // Scan gates from 0 to 249 (vertical resolution 250px)
+ sendCommand(0x01);
+ sendData(0xF9); // Maximum gate # (249, bits 0-7)
+ sendData(0x00); // Maximum gate # (bit 8)
+ sendData(0x00); // (Do not invert scanning order)
+}
+
+// Specify which information is used to control the sequence of voltages applied to move the pixels
+// - For this display, configUpdateSequence() specifies that a suitable LUT will be loaded from
+// the controller IC's OTP memory, when the update procedure begins.
+void HINK_E0213A289::configWaveform()
+{
+ sendCommand(0x3C); // Border waveform:
+ sendData(0x05); // Screen border should follow LUT1 waveform (actively drive pixels white)
+
+ sendCommand(0x18); // Temperature sensor:
+ sendData(0x80); // Use internal temperature sensor to select an appropriate refresh waveform
+}
+
+// Describes the sequence of events performed by the displays controller IC during a refresh
+// Includes "power up", "load settings from memory", "update the pixels", etc
+void HINK_E0213A289::configUpdateSequence()
+{
+ switch (updateType) {
+ case FAST:
+ sendCommand(0x22); // Set "update sequence"
+ sendData(0xFF); // Will load LUT from OTP memory, Display mode 2 "differential refresh"
+ break;
+
+ case FULL:
+ default:
+ sendCommand(0x22); // Set "update sequence"
+ sendData(0xF7); // Will load LUT from OTP memory
+ break;
+ }
+}
+
+// Once the refresh operation has been started,
+// begin periodically polling the display to check for completion, using the normal Meshtastic threading code
+// Only used when refresh is "async"
+void HINK_E0213A289::detachFromUpdate()
+{
+ switch (updateType) {
+ case FAST:
+ return beginPolling(50, 500); // At least 500ms for fast refresh
+ case FULL:
+ default:
+ return beginPolling(100, 1000); // At least 1 second for full refresh (quick; display only blinks pixels once)
+ }
+}
+#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
\ No newline at end of file
diff --git a/src/graphics/niche/Drivers/EInk/HINK_E0213A289.h b/src/graphics/niche/Drivers/EInk/HINK_E0213A289.h
new file mode 100644
index 000000000..eab0bf59d
--- /dev/null
+++ b/src/graphics/niche/Drivers/EInk/HINK_E0213A289.h
@@ -0,0 +1,44 @@
+/*
+
+E-Ink display driver
+ - HINK_E0213A289
+ - Manufacturer: Holitech
+ - Size: 2.13 inch
+ - Resolution: 122px x 250px
+ - Flex connector label (not a unique identifier): FPC-7528B
+
+ Note: as of Feb. 2025, these panels are used for "WeActStudio 2.13in B&W" display modules
+
+*/
+
+#pragma once
+
+#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
+
+#include "configuration.h"
+
+#include "./SSD16XX.h"
+
+namespace NicheGraphics::Drivers
+{
+class HINK_E0213A289 : public SSD16XX
+{
+ // Display properties
+ private:
+ static constexpr uint32_t width = 122;
+ static constexpr uint32_t height = 250;
+ static constexpr UpdateTypes supported = (UpdateTypes)(FULL | FAST);
+
+ public:
+ HINK_E0213A289() : SSD16XX(width, height, supported, 1) {}
+
+ protected:
+ void configScanning() override;
+ void configWaveform() override;
+ void configUpdateSequence() override;
+ void detachFromUpdate() override;
+};
+
+} // namespace NicheGraphics::Drivers
+
+#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
\ No newline at end of file
diff --git a/src/graphics/niche/Drivers/EInk/ZJY200200_0154DAAMFGN.h b/src/graphics/niche/Drivers/EInk/ZJY200200_0154DAAMFGN.h
new file mode 100644
index 000000000..fb16bcf2f
--- /dev/null
+++ b/src/graphics/niche/Drivers/EInk/ZJY200200_0154DAAMFGN.h
@@ -0,0 +1,32 @@
+/*
+
+E-Ink display driver
+ - ZJY200200-0154DAAMFGN
+ - Manufacturer: Zhongjingyuan
+ - Size: 1.54 inch
+ - Resolution: 200px x 200px
+ - Flex connector marking: FPC-B001
+
+ Note: as of Feb. 2025, these panels are used for "WeActStudio 1.54in B&W" display modules
+
+ This *is* a distinct panel, however the driver is currently identical to GDEY0154D67
+ We recognize it as separate now, to avoid breaking any custom builds if the drivers do need to diverge in future.
+
+*/
+
+#pragma once
+
+#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
+
+#include "configuration.h"
+
+#include "./GDEY0154D67.h"
+
+namespace NicheGraphics::Drivers
+{
+
+typedef GDEY0154D67 ZJY200200_0154DAAMFGN;
+
+} // namespace NicheGraphics::Drivers
+
+#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
\ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
index 2d49b2fbe..a35a5007f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -337,12 +337,22 @@ void setup()
#ifdef LED_POWER
pinMode(LED_POWER, OUTPUT);
- digitalWrite(LED_POWER, HIGH);
+ digitalWrite(LED_POWER, LED_STATE_ON);
#endif
#ifdef USER_LED
pinMode(USER_LED, OUTPUT);
- digitalWrite(USER_LED, LOW);
+ digitalWrite(USER_LED, HIGH ^ LED_STATE_ON);
+#endif
+
+#ifdef WIFI_LED
+ pinMode(WIFI_LED, OUTPUT);
+ digitalWrite(WIFI_LED, LOW);
+#endif
+
+#ifdef BLE_LED
+ pinMode(BLE_LED, OUTPUT);
+ digitalWrite(BLE_LED, LOW);
#endif
#if defined(T_DECK)
@@ -918,6 +928,11 @@ void setup()
service = new MeshService();
service->init();
+ if (nodeDB->keyIsLowEntropy) {
+ service->reloadConfig(SEGMENT_CONFIG);
+ rebootAtMsec = (millis() + DEFAULT_REBOOT_SECONDS * 1000);
+ }
+
// Now that the mesh service is created, create any modules
setupModules();
diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp
index 0a79f94a8..9ee430242 100644
--- a/src/mesh/NodeDB.cpp
+++ b/src/mesh/NodeDB.cpp
@@ -8,6 +8,7 @@
#include "Default.h"
#include "FSCommon.h"
#include "MeshRadio.h"
+#include "MeshService.h"
#include "NodeDB.h"
#include "PacketHistory.h"
#include "PowerFSM.h"
@@ -287,6 +288,16 @@ NodeDB::NodeDB()
crypto->setDHPrivateKey(config.security.private_key.bytes);
}
#endif
+ keyIsLowEntropy = checkLowEntropyPublicKey(config.security.public_key);
+ if (keyIsLowEntropy) {
+ LOG_WARN("Erasing low entropy keys");
+ config.security.private_key.size = 0;
+ memfll(config.security.private_key.bytes, '\0', sizeof(config.security.private_key.bytes));
+ config.security.public_key.size = 0;
+ memfll(config.security.public_key.bytes, '\0', sizeof(config.security.public_key.bytes));
+ owner.public_key.size = 0;
+ memfll(owner.public_key.bytes, '\0', sizeof(owner.public_key.bytes));
+ }
// Include our owner in the node db under our nodenum
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(getNodeNum());
info->user = TypeConversions::ConvertToUserLite(owner);
@@ -499,6 +510,21 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
true; // FIXME: maybe false in the future, and setting region to enable it. (unset region forces it off)
config.lora.override_duty_cycle = false;
config.lora.config_ok_to_mqtt = false;
+
+#ifdef USERPREFS_CONFIG_DEVICE_ROLE
+ // Restrict ROUTER*, LOST AND FOUND, and REPEATER roles for security reasons
+ if (IS_ONE_OF(USERPREFS_CONFIG_DEVICE_ROLE, meshtastic_Config_DeviceConfig_Role_ROUTER,
+ meshtastic_Config_DeviceConfig_Role_ROUTER_LATE, meshtastic_Config_DeviceConfig_Role_REPEATER,
+ meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND)) {
+ LOG_WARN("ROUTER roles are restricted, falling back to CLIENT role");
+ config.device.role = meshtastic_Config_DeviceConfig_Role_CLIENT;
+ } else {
+ config.device.role = USERPREFS_CONFIG_DEVICE_ROLE;
+ }
+#else
+ config.device.role = meshtastic_Config_DeviceConfig_Role_CLIENT; // Default to client.
+#endif
+
#ifdef USERPREFS_CONFIG_LORA_REGION
config.lora.region = USERPREFS_CONFIG_LORA_REGION;
#else
@@ -671,6 +697,11 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
}
#endif
+#ifdef USERPREFS_CONFIG_DEVICE_ROLE
+ // Apply role-specific defaults when role is set via user preferences
+ installRoleDefaults(config.device.role);
+#endif
+
initConfigIntervals();
}
@@ -1536,8 +1567,22 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde
}
#if !(MESHTASTIC_EXCLUDE_PKI)
- if (p.public_key.size > 0) {
+ if (p.public_key.size == 32) {
printBytes("Incoming Pubkey: ", p.public_key.bytes, 32);
+
+ // Alert the user if a remote node is advertising public key that matches our own
+ if (owner.public_key.size == 32 && memcmp(p.public_key.bytes, owner.public_key.bytes, 32) == 0 && !duplicateWarned) {
+ duplicateWarned = true;
+ char warning[] = "Remote device %s has advertised your public key. This may indicate a low-entropy key. You may need "
+ "to regenerate your public keys.";
+ LOG_WARN(warning, p.long_name);
+ meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
+ cn->which_payload_variant = meshtastic_ClientNotification_duplicated_public_key_tag;
+ cn->level = meshtastic_LogRecord_Level_WARNING;
+ cn->time = getValidTime(RTCQualityFromNet);
+ sprintf(cn->message, warning, p.long_name);
+ service->sendClientNotification(cn);
+ }
}
if (info->user.public_key.size > 0) { // if we have a key for this user already, don't overwrite with a new one
LOG_INFO("Public Key set for node, not updating!");
@@ -1712,6 +1757,33 @@ UserLicenseStatus NodeDB::getLicenseStatus(uint32_t nodeNum)
return info->user.is_licensed ? UserLicenseStatus::Licensed : UserLicenseStatus::NotLicensed;
}
+bool NodeDB::checkLowEntropyPublicKey(const meshtastic_Config_SecurityConfig_public_key_t keyToTest)
+{
+ if (keyToTest.size == 32) {
+ uint8_t keyHash[32] = {0};
+ memcpy(keyHash, keyToTest.bytes, keyToTest.size);
+ crypto->hash(keyHash, 32);
+ if (memcmp(keyHash, LOW_ENTROPY_HASH1, sizeof(LOW_ENTROPY_HASH1)) == 0 ||
+ memcmp(keyHash, LOW_ENTROPY_HASH2, sizeof(LOW_ENTROPY_HASH2)) == 0 ||
+ memcmp(keyHash, LOW_ENTROPY_HASH3, sizeof(LOW_ENTROPY_HASH3)) == 0 ||
+ memcmp(keyHash, LOW_ENTROPY_HASH4, sizeof(LOW_ENTROPY_HASH4)) == 0 ||
+ memcmp(keyHash, LOW_ENTROPY_HASH5, sizeof(LOW_ENTROPY_HASH5)) == 0 ||
+ memcmp(keyHash, LOW_ENTROPY_HASH6, sizeof(LOW_ENTROPY_HASH6)) == 0 ||
+ memcmp(keyHash, LOW_ENTROPY_HASH7, sizeof(LOW_ENTROPY_HASH7)) == 0 ||
+ memcmp(keyHash, LOW_ENTROPY_HASH8, sizeof(LOW_ENTROPY_HASH8)) == 0 ||
+ memcmp(keyHash, LOW_ENTROPY_HASH9, sizeof(LOW_ENTROPY_HASH9)) == 0 ||
+ memcmp(keyHash, LOW_ENTROPY_HASH10, sizeof(LOW_ENTROPY_HASH10)) == 0 ||
+ memcmp(keyHash, LOW_ENTROPY_HASH11, sizeof(LOW_ENTROPY_HASH11)) == 0 ||
+ memcmp(keyHash, LOW_ENTROPY_HASH12, sizeof(LOW_ENTROPY_HASH12)) == 0 ||
+ memcmp(keyHash, LOW_ENTROPY_HASH13, sizeof(LOW_ENTROPY_HASH13)) == 0 ||
+ memcmp(keyHash, LOW_ENTROPY_HASH14, sizeof(LOW_ENTROPY_HASH14)) == 0 ||
+ memcmp(keyHash, LOW_ENTROPY_HASH15, sizeof(LOW_ENTROPY_HASH15)) == 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
bool NodeDB::backupPreferences(meshtastic_AdminMessage_BackupLocation location)
{
bool success = false;
@@ -1822,4 +1894,4 @@ void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, co
LOG_ERROR("A critical failure occurred, portduino is exiting");
exit(2);
#endif
-}
\ No newline at end of file
+}
diff --git a/src/mesh/NodeDB.h b/src/mesh/NodeDB.h
index 16159d380..7e294f5b8 100644
--- a/src/mesh/NodeDB.h
+++ b/src/mesh/NodeDB.h
@@ -17,6 +17,55 @@
#include "PortduinoGlue.h"
#endif
+#if !defined(MESHTASTIC_EXCLUDE_PKI)
+
+static const uint8_t LOW_ENTROPY_HASH1[] = {0xf4, 0x7e, 0xcc, 0x17, 0xe6, 0xb4, 0xa3, 0x22, 0xec, 0xee, 0xd9,
+ 0x08, 0x4f, 0x39, 0x63, 0xea, 0x80, 0x75, 0xe1, 0x24, 0xce, 0x05,
+ 0x36, 0x69, 0x63, 0xb2, 0xcb, 0xc0, 0x28, 0xd3, 0x34, 0x8b};
+static const uint8_t LOW_ENTROPY_HASH2[] = {0x5a, 0x9e, 0xa2, 0xa6, 0x8a, 0xa6, 0x66, 0xc1, 0x5f, 0x55, 0x00,
+ 0x64, 0xa3, 0xa6, 0xfe, 0x71, 0xc0, 0xbb, 0x82, 0xc3, 0x32, 0x3d,
+ 0x7a, 0x7a, 0xe3, 0x6e, 0xfd, 0xdd, 0xad, 0x3a, 0x66, 0xb9};
+static const uint8_t LOW_ENTROPY_HASH3[] = {0xb3, 0xdf, 0x3b, 0x2e, 0x67, 0xb6, 0xd5, 0xf8, 0xdf, 0x76, 0x2c,
+ 0x45, 0x5e, 0x2e, 0xbd, 0x16, 0xc5, 0xf8, 0x67, 0xaa, 0x15, 0xf8,
+ 0x92, 0x0b, 0xdf, 0x5a, 0x66, 0x50, 0xac, 0x0d, 0xbb, 0x2f};
+static const uint8_t LOW_ENTROPY_HASH4[] = {0x3b, 0x8f, 0x86, 0x3a, 0x38, 0x1f, 0x77, 0x39, 0xa9, 0x4e, 0xef,
+ 0x91, 0x18, 0x5a, 0x62, 0xe1, 0xaa, 0x9d, 0x36, 0xea, 0xce, 0x60,
+ 0x35, 0x8d, 0x9d, 0x1f, 0xf4, 0xb8, 0xc9, 0x13, 0x6a, 0x5d};
+static const uint8_t LOW_ENTROPY_HASH5[] = {0x36, 0x7e, 0x2d, 0xe1, 0x84, 0x5f, 0x42, 0x52, 0x29, 0x11, 0x0a,
+ 0x25, 0x64, 0x54, 0x6a, 0x6b, 0xfd, 0xb6, 0x65, 0xff, 0x15, 0x1a,
+ 0x51, 0x71, 0x22, 0x40, 0x57, 0xf6, 0x91, 0x9b, 0x64, 0x58};
+static const uint8_t LOW_ENTROPY_HASH6[] = {0x16, 0x77, 0xeb, 0xa4, 0x52, 0x91, 0xfb, 0x26, 0xcf, 0x8f, 0xd7,
+ 0xd9, 0xd1, 0x5d, 0xc4, 0x68, 0x73, 0x75, 0xed, 0xc5, 0x95, 0x58,
+ 0xee, 0x90, 0x56, 0xd4, 0x2f, 0x31, 0x29, 0xf7, 0x8c, 0x1f};
+static const uint8_t LOW_ENTROPY_HASH7[] = {0x31, 0x8c, 0xa9, 0x5e, 0xed, 0x3c, 0x12, 0xbf, 0x97, 0x9c, 0x47,
+ 0x8e, 0x98, 0x9d, 0xc2, 0x3e, 0x86, 0x23, 0x90, 0x29, 0xc8, 0xb0,
+ 0x20, 0xf8, 0xb1, 0xb0, 0xaa, 0x19, 0x2a, 0xcf, 0x0a, 0x54};
+static const uint8_t LOW_ENTROPY_HASH8[] = {0xa4, 0x8a, 0x99, 0x0e, 0x51, 0xdc, 0x12, 0x20, 0xf3, 0x13, 0xf5,
+ 0x2b, 0x3a, 0xe2, 0x43, 0x42, 0xc6, 0x52, 0x98, 0xcd, 0xbb, 0xca,
+ 0xb1, 0x31, 0xa0, 0xd4, 0xd6, 0x30, 0xf3, 0x27, 0xfb, 0x49};
+static const uint8_t LOW_ENTROPY_HASH9[] = {0xd2, 0x3f, 0x13, 0x8d, 0x22, 0x04, 0x8d, 0x07, 0x59, 0x58, 0xa0,
+ 0xf9, 0x55, 0xcf, 0x30, 0xa0, 0x2e, 0x2f, 0xca, 0x80, 0x20, 0xe4,
+ 0xde, 0xa1, 0xad, 0xd9, 0x58, 0xb3, 0x43, 0x2b, 0x22, 0x70};
+static const uint8_t LOW_ENTROPY_HASH10[] = {0x40, 0x41, 0xec, 0x6a, 0xd2, 0xd6, 0x03, 0xe4, 0x9a, 0x9e, 0xbd,
+ 0x6c, 0x0a, 0x9b, 0x75, 0xa4, 0xbc, 0xab, 0x6f, 0xa7, 0x95, 0xff,
+ 0x2d, 0xf6, 0xe9, 0xb9, 0xab, 0x4c, 0x0c, 0x1c, 0xd0, 0x3b};
+static const uint8_t LOW_ENTROPY_HASH11[] = {0x22, 0x49, 0x32, 0x2b, 0x00, 0xf9, 0x22, 0xfa, 0x17, 0x02, 0xe9,
+ 0x64, 0x82, 0xf0, 0x4d, 0x1b, 0xc7, 0x04, 0xfc, 0xdc, 0x8c, 0x5e,
+ 0xb6, 0xd9, 0x16, 0xd6, 0x37, 0xce, 0x59, 0xaa, 0x09, 0x49};
+static const uint8_t LOW_ENTROPY_HASH12[] = {0x48, 0x6f, 0x1e, 0x48, 0x97, 0x88, 0x64, 0xac, 0xe8, 0xeb, 0x30,
+ 0xa3, 0xc3, 0xe1, 0xcf, 0x97, 0x39, 0xa6, 0x55, 0x5b, 0x5f, 0xbf,
+ 0x18, 0xb7, 0x3a, 0xdf, 0xa8, 0x75, 0xe7, 0x9d, 0xe0, 0x1e};
+static const uint8_t LOW_ENTROPY_HASH13[] = {0x09, 0xb4, 0xe2, 0x6d, 0x28, 0x98, 0xc9, 0x47, 0x66, 0x46, 0xbf,
+ 0xff, 0x58, 0x17, 0x91, 0xaa, 0xc3, 0xbf, 0x4a, 0x9d, 0x0b, 0x88,
+ 0xb1, 0xf1, 0x03, 0xdd, 0x61, 0xd7, 0xba, 0x9e, 0x64, 0x98};
+static const uint8_t LOW_ENTROPY_HASH14[] = {0x39, 0x39, 0x84, 0xe0, 0x22, 0x2f, 0x7d, 0x78, 0x45, 0x18, 0x72,
+ 0xb4, 0x13, 0xd2, 0x01, 0x2f, 0x3c, 0xa1, 0xb0, 0xfe, 0x39, 0xd0,
+ 0xf1, 0x3c, 0x72, 0xd6, 0xef, 0x54, 0xd5, 0x77, 0x22, 0xa0};
+static const uint8_t LOW_ENTROPY_HASH15[] = {0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4,
+ 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b,
+ 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55};
+static const char LOW_ENTROPY_WARNING[] = "Your Device is configured with a low entropy key. Suggest regenerating DM keys";
+#endif
/*
DeviceState versions used to be defined in the .proto file but really only this function cares. So changed to a
#define here.
@@ -87,6 +136,9 @@ class NodeDB
Observable newStatus;
pb_size_t numMeshNodes;
+ bool keyIsLowEntropy = false;
+ bool hasWarned = false;
+
/// don't do mesh based algorithm for node id assignment (initially)
/// instead just store in flash - possibly even in the initial alpha release do this hack
NodeDB();
@@ -205,11 +257,14 @@ class NodeDB
bool hasValidPosition(const meshtastic_NodeInfoLite *n);
+ bool checkLowEntropyPublicKey(const meshtastic_Config_SecurityConfig_public_key_t keyToTest);
+
bool backupPreferences(meshtastic_AdminMessage_BackupLocation location);
bool restorePreferences(meshtastic_AdminMessage_BackupLocation location,
int restoreWhat = SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS);
private:
+ bool duplicateWarned = false;
uint32_t lastNodeDbSave = 0; // when we last saved our db to flash
uint32_t lastBackupAttempt = 0; // when we last tried a backup automatically or manually
/// Find a node in our DB, create an empty NodeInfoLite if missing
diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp
index fef29388e..02968513c 100644
--- a/src/mesh/Router.cpp
+++ b/src/mesh/Router.cpp
@@ -548,6 +548,20 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
numbytes += MESHTASTIC_PKC_OVERHEAD;
p->channel = 0;
p->pki_encrypted = true;
+
+ // warn the user about a low entropy key
+ if (nodeDB->keyIsLowEntropy) {
+ LOG_WARN(LOW_ENTROPY_WARNING);
+ if (!nodeDB->hasWarned) {
+ meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
+ cn->which_payload_variant = meshtastic_ClientNotification_low_entropy_key_tag;
+ cn->level = meshtastic_LogRecord_Level_WARNING;
+ cn->time = getValidTime(RTCQualityFromNet);
+ sprintf(cn->message, LOW_ENTROPY_WARNING);
+ service->sendClientNotification(cn);
+ nodeDB->hasWarned = true;
+ }
+ }
} else {
if (p->pki_encrypted == true) {
// Client specifically requested PKI encryption
diff --git a/src/mesh/generated/meshtastic/admin.pb.cpp b/src/mesh/generated/meshtastic/admin.pb.cpp
index a9c82f7c0..4c4d0e3d1 100644
--- a/src/mesh/generated/meshtastic/admin.pb.cpp
+++ b/src/mesh/generated/meshtastic/admin.pb.cpp
@@ -9,6 +9,9 @@
PB_BIND(meshtastic_AdminMessage, meshtastic_AdminMessage, 2)
+PB_BIND(meshtastic_AdminMessage_InputEvent, meshtastic_AdminMessage_InputEvent, AUTO)
+
+
PB_BIND(meshtastic_HamParameters, meshtastic_HamParameters, AUTO)
diff --git a/src/mesh/generated/meshtastic/admin.pb.h b/src/mesh/generated/meshtastic/admin.pb.h
index 2a5fd78b0..c111d3993 100644
--- a/src/mesh/generated/meshtastic/admin.pb.h
+++ b/src/mesh/generated/meshtastic/admin.pb.h
@@ -91,6 +91,18 @@ typedef enum _meshtastic_KeyVerificationAdmin_MessageType {
} meshtastic_KeyVerificationAdmin_MessageType;
/* Struct definitions */
+/* Input event message to be sent to the node. */
+typedef struct _meshtastic_AdminMessage_InputEvent {
+ /* The input event code */
+ uint8_t event_code;
+ /* Keyboard character code */
+ uint8_t kb_char;
+ /* The touch X coordinate */
+ uint16_t touch_x;
+ /* The touch Y coordinate */
+ uint16_t touch_y;
+} meshtastic_AdminMessage_InputEvent;
+
/* Parameters for setting up Meshtastic for ameteur radio usage */
typedef struct _meshtastic_HamParameters {
/* Amateur radio call sign, eg. KD2ABC */
@@ -191,6 +203,9 @@ typedef struct _meshtastic_AdminMessage {
meshtastic_AdminMessage_BackupLocation restore_preferences;
/* Remove backups of the node's preferences */
meshtastic_AdminMessage_BackupLocation remove_backup_preferences;
+ /* Send an input event to the node.
+ This is used to trigger physical input events like button presses, touch events, etc. */
+ meshtastic_AdminMessage_InputEvent send_input_event;
/* Set the owner for this node */
meshtastic_User set_owner;
/* Set channels (using the new API).
@@ -293,22 +308,29 @@ extern "C" {
+
#define meshtastic_KeyVerificationAdmin_message_type_ENUMTYPE meshtastic_KeyVerificationAdmin_MessageType
/* Initializer values for message structs */
#define meshtastic_AdminMessage_init_default {0, {0}, {0, {0}}}
+#define meshtastic_AdminMessage_InputEvent_init_default {0, 0, 0, 0}
#define meshtastic_HamParameters_init_default {"", 0, 0, ""}
#define meshtastic_NodeRemoteHardwarePinsResponse_init_default {0, {meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default}}
#define meshtastic_SharedContact_init_default {0, false, meshtastic_User_init_default}
#define meshtastic_KeyVerificationAdmin_init_default {_meshtastic_KeyVerificationAdmin_MessageType_MIN, 0, 0, false, 0}
#define meshtastic_AdminMessage_init_zero {0, {0}, {0, {0}}}
+#define meshtastic_AdminMessage_InputEvent_init_zero {0, 0, 0, 0}
#define meshtastic_HamParameters_init_zero {"", 0, 0, ""}
#define meshtastic_NodeRemoteHardwarePinsResponse_init_zero {0, {meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero}}
#define meshtastic_SharedContact_init_zero {0, false, meshtastic_User_init_zero}
#define meshtastic_KeyVerificationAdmin_init_zero {_meshtastic_KeyVerificationAdmin_MessageType_MIN, 0, 0, false, 0}
/* Field tags (for use in manual encoding/decoding) */
+#define meshtastic_AdminMessage_InputEvent_event_code_tag 1
+#define meshtastic_AdminMessage_InputEvent_kb_char_tag 2
+#define meshtastic_AdminMessage_InputEvent_touch_x_tag 3
+#define meshtastic_AdminMessage_InputEvent_touch_y_tag 4
#define meshtastic_HamParameters_call_sign_tag 1
#define meshtastic_HamParameters_tx_power_tag 2
#define meshtastic_HamParameters_frequency_tag 3
@@ -345,6 +367,7 @@ extern "C" {
#define meshtastic_AdminMessage_backup_preferences_tag 24
#define meshtastic_AdminMessage_restore_preferences_tag 25
#define meshtastic_AdminMessage_remove_backup_preferences_tag 26
+#define meshtastic_AdminMessage_send_input_event_tag 27
#define meshtastic_AdminMessage_set_owner_tag 32
#define meshtastic_AdminMessage_set_channel_tag 33
#define meshtastic_AdminMessage_set_config_tag 34
@@ -402,6 +425,7 @@ X(a, STATIC, ONEOF, UINT32, (payload_variant,set_scale,set_scale), 23) \
X(a, STATIC, ONEOF, UENUM, (payload_variant,backup_preferences,backup_preferences), 24) \
X(a, STATIC, ONEOF, UENUM, (payload_variant,restore_preferences,restore_preferences), 25) \
X(a, STATIC, ONEOF, UENUM, (payload_variant,remove_backup_preferences,remove_backup_preferences), 26) \
+X(a, STATIC, ONEOF, MESSAGE, (payload_variant,send_input_event,send_input_event), 27) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_owner,set_owner), 32) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_channel,set_channel), 33) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_config,set_config), 34) \
@@ -441,6 +465,7 @@ X(a, STATIC, SINGULAR, BYTES, session_passkey, 101)
#define meshtastic_AdminMessage_payload_variant_get_device_connection_status_response_MSGTYPE meshtastic_DeviceConnectionStatus
#define meshtastic_AdminMessage_payload_variant_set_ham_mode_MSGTYPE meshtastic_HamParameters
#define meshtastic_AdminMessage_payload_variant_get_node_remote_hardware_pins_response_MSGTYPE meshtastic_NodeRemoteHardwarePinsResponse
+#define meshtastic_AdminMessage_payload_variant_send_input_event_MSGTYPE meshtastic_AdminMessage_InputEvent
#define meshtastic_AdminMessage_payload_variant_set_owner_MSGTYPE meshtastic_User
#define meshtastic_AdminMessage_payload_variant_set_channel_MSGTYPE meshtastic_Channel
#define meshtastic_AdminMessage_payload_variant_set_config_MSGTYPE meshtastic_Config
@@ -451,6 +476,14 @@ X(a, STATIC, SINGULAR, BYTES, session_passkey, 101)
#define meshtastic_AdminMessage_payload_variant_add_contact_MSGTYPE meshtastic_SharedContact
#define meshtastic_AdminMessage_payload_variant_key_verification_MSGTYPE meshtastic_KeyVerificationAdmin
+#define meshtastic_AdminMessage_InputEvent_FIELDLIST(X, a) \
+X(a, STATIC, SINGULAR, UINT32, event_code, 1) \
+X(a, STATIC, SINGULAR, UINT32, kb_char, 2) \
+X(a, STATIC, SINGULAR, UINT32, touch_x, 3) \
+X(a, STATIC, SINGULAR, UINT32, touch_y, 4)
+#define meshtastic_AdminMessage_InputEvent_CALLBACK NULL
+#define meshtastic_AdminMessage_InputEvent_DEFAULT NULL
+
#define meshtastic_HamParameters_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, STRING, call_sign, 1) \
X(a, STATIC, SINGULAR, INT32, tx_power, 2) \
@@ -481,6 +514,7 @@ X(a, STATIC, OPTIONAL, UINT32, security_number, 4)
#define meshtastic_KeyVerificationAdmin_DEFAULT NULL
extern const pb_msgdesc_t meshtastic_AdminMessage_msg;
+extern const pb_msgdesc_t meshtastic_AdminMessage_InputEvent_msg;
extern const pb_msgdesc_t meshtastic_HamParameters_msg;
extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePinsResponse_msg;
extern const pb_msgdesc_t meshtastic_SharedContact_msg;
@@ -488,6 +522,7 @@ extern const pb_msgdesc_t meshtastic_KeyVerificationAdmin_msg;
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
#define meshtastic_AdminMessage_fields &meshtastic_AdminMessage_msg
+#define meshtastic_AdminMessage_InputEvent_fields &meshtastic_AdminMessage_InputEvent_msg
#define meshtastic_HamParameters_fields &meshtastic_HamParameters_msg
#define meshtastic_NodeRemoteHardwarePinsResponse_fields &meshtastic_NodeRemoteHardwarePinsResponse_msg
#define meshtastic_SharedContact_fields &meshtastic_SharedContact_msg
@@ -495,6 +530,7 @@ extern const pb_msgdesc_t meshtastic_KeyVerificationAdmin_msg;
/* Maximum encoded size of messages (where known) */
#define MESHTASTIC_MESHTASTIC_ADMIN_PB_H_MAX_SIZE meshtastic_AdminMessage_size
+#define meshtastic_AdminMessage_InputEvent_size 14
#define meshtastic_AdminMessage_size 511
#define meshtastic_HamParameters_size 31
#define meshtastic_KeyVerificationAdmin_size 25
diff --git a/src/mesh/generated/meshtastic/config.pb.cpp b/src/mesh/generated/meshtastic/config.pb.cpp
index 5512584a7..52a591f33 100644
--- a/src/mesh/generated/meshtastic/config.pb.cpp
+++ b/src/mesh/generated/meshtastic/config.pb.cpp
@@ -65,6 +65,8 @@ PB_BIND(meshtastic_Config_SessionkeyConfig, meshtastic_Config_SessionkeyConfig,
+
+
diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h
index 9d7a96dc8..6851d42b1 100644
--- a/src/mesh/generated/meshtastic/config.pb.h
+++ b/src/mesh/generated/meshtastic/config.pb.h
@@ -88,6 +88,23 @@ typedef enum _meshtastic_Config_DeviceConfig_RebroadcastMode {
meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY = 5
} meshtastic_Config_DeviceConfig_RebroadcastMode;
+/* Defines buzzer behavior for audio feedback */
+typedef enum _meshtastic_Config_DeviceConfig_BuzzerMode {
+ /* Default behavior.
+ Buzzer is enabled for all audio feedback including button presses and alerts. */
+ meshtastic_Config_DeviceConfig_BuzzerMode_ALL_ENABLED = 0,
+ /* Disabled.
+ All buzzer audio feedback is disabled. */
+ meshtastic_Config_DeviceConfig_BuzzerMode_DISABLED = 1,
+ /* Notifications Only.
+ Buzzer is enabled only for notifications and alerts, but not for button presses.
+ External notification config determines the specifics of the notification behavior. */
+ meshtastic_Config_DeviceConfig_BuzzerMode_NOTIFICATIONS_ONLY = 2,
+ /* Non-notification system buzzer tones only.
+ Buzzer is enabled only for non-notification tones such as button presses, startup, shutdown, but not for alerts. */
+ meshtastic_Config_DeviceConfig_BuzzerMode_SYSTEM_ONLY = 3
+} meshtastic_Config_DeviceConfig_BuzzerMode;
+
/* Bit field of boolean configuration options, indicating which optional
fields to include when assembling POSITION messages.
Longitude, latitude, altitude, speed, heading, and DOP
@@ -335,6 +352,9 @@ typedef struct _meshtastic_Config_DeviceConfig {
char tzdef[65];
/* If true, disable the default blinking LED (LED_PIN) behavior on the device */
bool led_heartbeat_disabled;
+ /* Controls buzzer behavior for audio feedback
+ Defaults to ENABLED */
+ meshtastic_Config_DeviceConfig_BuzzerMode buzzer_mode;
} meshtastic_Config_DeviceConfig;
/* Position Config */
@@ -618,6 +638,10 @@ extern "C" {
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MAX meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_ARRAYSIZE ((meshtastic_Config_DeviceConfig_RebroadcastMode)(meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY+1))
+#define _meshtastic_Config_DeviceConfig_BuzzerMode_MIN meshtastic_Config_DeviceConfig_BuzzerMode_ALL_ENABLED
+#define _meshtastic_Config_DeviceConfig_BuzzerMode_MAX meshtastic_Config_DeviceConfig_BuzzerMode_SYSTEM_ONLY
+#define _meshtastic_Config_DeviceConfig_BuzzerMode_ARRAYSIZE ((meshtastic_Config_DeviceConfig_BuzzerMode)(meshtastic_Config_DeviceConfig_BuzzerMode_SYSTEM_ONLY+1))
+
#define _meshtastic_Config_PositionConfig_PositionFlags_MIN meshtastic_Config_PositionConfig_PositionFlags_UNSET
#define _meshtastic_Config_PositionConfig_PositionFlags_MAX meshtastic_Config_PositionConfig_PositionFlags_SPEED
#define _meshtastic_Config_PositionConfig_PositionFlags_ARRAYSIZE ((meshtastic_Config_PositionConfig_PositionFlags)(meshtastic_Config_PositionConfig_PositionFlags_SPEED+1))
@@ -669,6 +693,7 @@ extern "C" {
#define meshtastic_Config_DeviceConfig_role_ENUMTYPE meshtastic_Config_DeviceConfig_Role
#define meshtastic_Config_DeviceConfig_rebroadcast_mode_ENUMTYPE meshtastic_Config_DeviceConfig_RebroadcastMode
+#define meshtastic_Config_DeviceConfig_buzzer_mode_ENUMTYPE meshtastic_Config_DeviceConfig_BuzzerMode
#define meshtastic_Config_PositionConfig_gps_mode_ENUMTYPE meshtastic_Config_PositionConfig_GpsMode
@@ -692,7 +717,7 @@ extern "C" {
/* Initializer values for message structs */
#define meshtastic_Config_init_default {0, {meshtastic_Config_DeviceConfig_init_default}}
-#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, "", 0}
+#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, "", 0, _meshtastic_Config_DeviceConfig_BuzzerMode_MIN}
#define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN}
#define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, "", 0, 0}
@@ -703,7 +728,7 @@ extern "C" {
#define meshtastic_Config_SecurityConfig_init_default {{0, {0}}, {0, {0}}, 0, {{0, {0}}, {0, {0}}, {0, {0}}}, 0, 0, 0, 0}
#define meshtastic_Config_SessionkeyConfig_init_default {0}
#define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}}
-#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, "", 0}
+#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, "", 0, _meshtastic_Config_DeviceConfig_BuzzerMode_MIN}
#define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN}
#define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, "", 0, 0}
@@ -726,6 +751,7 @@ extern "C" {
#define meshtastic_Config_DeviceConfig_disable_triple_click_tag 10
#define meshtastic_Config_DeviceConfig_tzdef_tag 11
#define meshtastic_Config_DeviceConfig_led_heartbeat_disabled_tag 12
+#define meshtastic_Config_DeviceConfig_buzzer_mode_tag 13
#define meshtastic_Config_PositionConfig_position_broadcast_secs_tag 1
#define meshtastic_Config_PositionConfig_position_broadcast_smart_enabled_tag 2
#define meshtastic_Config_PositionConfig_fixed_position_tag 3
@@ -849,7 +875,8 @@ X(a, STATIC, SINGULAR, BOOL, double_tap_as_button_press, 8) \
X(a, STATIC, SINGULAR, BOOL, is_managed, 9) \
X(a, STATIC, SINGULAR, BOOL, disable_triple_click, 10) \
X(a, STATIC, SINGULAR, STRING, tzdef, 11) \
-X(a, STATIC, SINGULAR, BOOL, led_heartbeat_disabled, 12)
+X(a, STATIC, SINGULAR, BOOL, led_heartbeat_disabled, 12) \
+X(a, STATIC, SINGULAR, UENUM, buzzer_mode, 13)
#define meshtastic_Config_DeviceConfig_CALLBACK NULL
#define meshtastic_Config_DeviceConfig_DEFAULT NULL
@@ -995,7 +1022,7 @@ extern const pb_msgdesc_t meshtastic_Config_SessionkeyConfig_msg;
/* Maximum encoded size of messages (where known) */
#define MESHTASTIC_MESHTASTIC_CONFIG_PB_H_MAX_SIZE meshtastic_Config_size
#define meshtastic_Config_BluetoothConfig_size 10
-#define meshtastic_Config_DeviceConfig_size 98
+#define meshtastic_Config_DeviceConfig_size 100
#define meshtastic_Config_DisplayConfig_size 32
#define meshtastic_Config_LoRaConfig_size 85
#define meshtastic_Config_NetworkConfig_IpV4Config_size 20
diff --git a/src/mesh/generated/meshtastic/device_ui.pb.h b/src/mesh/generated/meshtastic/device_ui.pb.h
index 5692a2749..3a8ddd3a4 100644
--- a/src/mesh/generated/meshtastic/device_ui.pb.h
+++ b/src/mesh/generated/meshtastic/device_ui.pb.h
@@ -55,6 +55,8 @@ typedef enum _meshtastic_Language {
meshtastic_Language_SLOVENIAN = 15,
/* Ukrainian */
meshtastic_Language_UKRAINIAN = 16,
+ /* Bulgarian */
+ meshtastic_Language_BULGARIAN = 17,
/* Simplified Chinese (experimental) */
meshtastic_Language_SIMPLIFIED_CHINESE = 30,
/* Traditional Chinese (experimental) */
diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h
index 37f99d8b5..f78689cb2 100644
--- a/src/mesh/generated/meshtastic/deviceonly.pb.h
+++ b/src/mesh/generated/meshtastic/deviceonly.pb.h
@@ -360,7 +360,7 @@ extern const pb_msgdesc_t meshtastic_BackupPreferences_msg;
/* Maximum encoded size of messages (where known) */
/* meshtastic_NodeDatabase_size depends on runtime parameters */
#define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size
-#define meshtastic_BackupPreferences_size 2269
+#define meshtastic_BackupPreferences_size 2271
#define meshtastic_ChannelFile_size 718
#define meshtastic_DeviceState_size 1722
#define meshtastic_NodeInfoLite_size 196
diff --git a/src/mesh/generated/meshtastic/localonly.pb.h b/src/mesh/generated/meshtastic/localonly.pb.h
index bb2eefc04..ca8dcd5fb 100644
--- a/src/mesh/generated/meshtastic/localonly.pb.h
+++ b/src/mesh/generated/meshtastic/localonly.pb.h
@@ -187,7 +187,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
/* Maximum encoded size of messages (where known) */
#define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalConfig_size
-#define meshtastic_LocalConfig_size 745
+#define meshtastic_LocalConfig_size 747
#define meshtastic_LocalModuleConfig_size 669
#ifdef __cplusplus
diff --git a/src/mesh/generated/meshtastic/mesh.pb.cpp b/src/mesh/generated/meshtastic/mesh.pb.cpp
index 11875fadd..361d01b9a 100644
--- a/src/mesh/generated/meshtastic/mesh.pb.cpp
+++ b/src/mesh/generated/meshtastic/mesh.pb.cpp
@@ -60,6 +60,12 @@ PB_BIND(meshtastic_KeyVerificationNumberRequest, meshtastic_KeyVerificationNumbe
PB_BIND(meshtastic_KeyVerificationFinal, meshtastic_KeyVerificationFinal, AUTO)
+PB_BIND(meshtastic_DuplicatedPublicKey, meshtastic_DuplicatedPublicKey, AUTO)
+
+
+PB_BIND(meshtastic_LowEntropyKey, meshtastic_LowEntropyKey, AUTO)
+
+
PB_BIND(meshtastic_FileInfo, meshtastic_FileInfo, AUTO)
diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h
index 5fc1cc4f5..b07c59625 100644
--- a/src/mesh/generated/meshtastic/mesh.pb.h
+++ b/src/mesh/generated/meshtastic/mesh.pb.h
@@ -258,6 +258,15 @@ typedef enum _meshtastic_HardwareModel {
meshtastic_HardwareModel_SEEED_WIO_TRACKER_L1_EINK = 100,
/* Reserved ID for future and past use */
meshtastic_HardwareModel_QWANTZ_TINY_ARMS = 101,
+ /* *
+ Lilygo T-Deck Pro */
+ meshtastic_HardwareModel_T_DECK_PRO = 102,
+ /* *
+ Lilygo TLora Pager */
+ meshtastic_HardwareModel_T_LORA_PAGER = 103,
+ /* *
+ GAT562 Mesh Trial Tracker */
+ meshtastic_HardwareModel_GAT562_MESH_TRIAL_TRACKER = 104,
/* ------------------------------------------------------------------------------------------------------------------------------------------
Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
------------------------------------------------------------------------------------------------------------------------------------------ */
@@ -949,6 +958,14 @@ typedef struct _meshtastic_KeyVerificationFinal {
char verification_characters[10];
} meshtastic_KeyVerificationFinal;
+typedef struct _meshtastic_DuplicatedPublicKey {
+ char dummy_field;
+} meshtastic_DuplicatedPublicKey;
+
+typedef struct _meshtastic_LowEntropyKey {
+ char dummy_field;
+} meshtastic_LowEntropyKey;
+
/* A notification message from the device to the client
To be used for important messages that should to be displayed to the user
in the form of push notifications or validation messages when saving
@@ -968,6 +985,8 @@ typedef struct _meshtastic_ClientNotification {
meshtastic_KeyVerificationNumberInform key_verification_number_inform;
meshtastic_KeyVerificationNumberRequest key_verification_number_request;
meshtastic_KeyVerificationFinal key_verification_final;
+ meshtastic_DuplicatedPublicKey duplicated_public_key;
+ meshtastic_LowEntropyKey low_entropy_key;
} payload_variant;
} meshtastic_ClientNotification;
@@ -1248,6 +1267,8 @@ extern "C" {
+
+
#define meshtastic_Compressed_portnum_ENUMTYPE meshtastic_PortNum
@@ -1280,6 +1301,8 @@ extern "C" {
#define meshtastic_KeyVerificationNumberInform_init_default {0, "", 0}
#define meshtastic_KeyVerificationNumberRequest_init_default {0, ""}
#define meshtastic_KeyVerificationFinal_init_default {0, "", 0, ""}
+#define meshtastic_DuplicatedPublicKey_init_default {0}
+#define meshtastic_LowEntropyKey_init_default {0}
#define meshtastic_FileInfo_init_default {"", 0}
#define meshtastic_ToRadio_init_default {0, {meshtastic_MeshPacket_init_default}}
#define meshtastic_Compressed_init_default {_meshtastic_PortNum_MIN, {0, {0}}}
@@ -1309,6 +1332,8 @@ extern "C" {
#define meshtastic_KeyVerificationNumberInform_init_zero {0, "", 0}
#define meshtastic_KeyVerificationNumberRequest_init_zero {0, ""}
#define meshtastic_KeyVerificationFinal_init_zero {0, "", 0, ""}
+#define meshtastic_DuplicatedPublicKey_init_zero {0}
+#define meshtastic_LowEntropyKey_init_zero {0}
#define meshtastic_FileInfo_init_zero {"", 0}
#define meshtastic_ToRadio_init_zero {0, {meshtastic_MeshPacket_init_zero}}
#define meshtastic_Compressed_init_zero {_meshtastic_PortNum_MIN, {0, {0}}}
@@ -1446,6 +1471,8 @@ extern "C" {
#define meshtastic_ClientNotification_key_verification_number_inform_tag 11
#define meshtastic_ClientNotification_key_verification_number_request_tag 12
#define meshtastic_ClientNotification_key_verification_final_tag 13
+#define meshtastic_ClientNotification_duplicated_public_key_tag 14
+#define meshtastic_ClientNotification_low_entropy_key_tag 15
#define meshtastic_FileInfo_file_name_tag 1
#define meshtastic_FileInfo_size_bytes_tag 2
#define meshtastic_Compressed_portnum_tag 1
@@ -1714,12 +1741,16 @@ X(a, STATIC, SINGULAR, UENUM, level, 3) \
X(a, STATIC, SINGULAR, STRING, message, 4) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,key_verification_number_inform,payload_variant.key_verification_number_inform), 11) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,key_verification_number_request,payload_variant.key_verification_number_request), 12) \
-X(a, STATIC, ONEOF, MESSAGE, (payload_variant,key_verification_final,payload_variant.key_verification_final), 13)
+X(a, STATIC, ONEOF, MESSAGE, (payload_variant,key_verification_final,payload_variant.key_verification_final), 13) \
+X(a, STATIC, ONEOF, MESSAGE, (payload_variant,duplicated_public_key,payload_variant.duplicated_public_key), 14) \
+X(a, STATIC, ONEOF, MESSAGE, (payload_variant,low_entropy_key,payload_variant.low_entropy_key), 15)
#define meshtastic_ClientNotification_CALLBACK NULL
#define meshtastic_ClientNotification_DEFAULT NULL
#define meshtastic_ClientNotification_payload_variant_key_verification_number_inform_MSGTYPE meshtastic_KeyVerificationNumberInform
#define meshtastic_ClientNotification_payload_variant_key_verification_number_request_MSGTYPE meshtastic_KeyVerificationNumberRequest
#define meshtastic_ClientNotification_payload_variant_key_verification_final_MSGTYPE meshtastic_KeyVerificationFinal
+#define meshtastic_ClientNotification_payload_variant_duplicated_public_key_MSGTYPE meshtastic_DuplicatedPublicKey
+#define meshtastic_ClientNotification_payload_variant_low_entropy_key_MSGTYPE meshtastic_LowEntropyKey
#define meshtastic_KeyVerificationNumberInform_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT64, nonce, 1) \
@@ -1742,6 +1773,16 @@ X(a, STATIC, SINGULAR, STRING, verification_characters, 4)
#define meshtastic_KeyVerificationFinal_CALLBACK NULL
#define meshtastic_KeyVerificationFinal_DEFAULT NULL
+#define meshtastic_DuplicatedPublicKey_FIELDLIST(X, a) \
+
+#define meshtastic_DuplicatedPublicKey_CALLBACK NULL
+#define meshtastic_DuplicatedPublicKey_DEFAULT NULL
+
+#define meshtastic_LowEntropyKey_FIELDLIST(X, a) \
+
+#define meshtastic_LowEntropyKey_CALLBACK NULL
+#define meshtastic_LowEntropyKey_DEFAULT NULL
+
#define meshtastic_FileInfo_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, STRING, file_name, 1) \
X(a, STATIC, SINGULAR, UINT32, size_bytes, 2)
@@ -1853,6 +1894,8 @@ extern const pb_msgdesc_t meshtastic_ClientNotification_msg;
extern const pb_msgdesc_t meshtastic_KeyVerificationNumberInform_msg;
extern const pb_msgdesc_t meshtastic_KeyVerificationNumberRequest_msg;
extern const pb_msgdesc_t meshtastic_KeyVerificationFinal_msg;
+extern const pb_msgdesc_t meshtastic_DuplicatedPublicKey_msg;
+extern const pb_msgdesc_t meshtastic_LowEntropyKey_msg;
extern const pb_msgdesc_t meshtastic_FileInfo_msg;
extern const pb_msgdesc_t meshtastic_ToRadio_msg;
extern const pb_msgdesc_t meshtastic_Compressed_msg;
@@ -1884,6 +1927,8 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
#define meshtastic_KeyVerificationNumberInform_fields &meshtastic_KeyVerificationNumberInform_msg
#define meshtastic_KeyVerificationNumberRequest_fields &meshtastic_KeyVerificationNumberRequest_msg
#define meshtastic_KeyVerificationFinal_fields &meshtastic_KeyVerificationFinal_msg
+#define meshtastic_DuplicatedPublicKey_fields &meshtastic_DuplicatedPublicKey_msg
+#define meshtastic_LowEntropyKey_fields &meshtastic_LowEntropyKey_msg
#define meshtastic_FileInfo_fields &meshtastic_FileInfo_msg
#define meshtastic_ToRadio_fields &meshtastic_ToRadio_msg
#define meshtastic_Compressed_fields &meshtastic_Compressed_msg
@@ -1905,6 +1950,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
#define meshtastic_Compressed_size 239
#define meshtastic_Data_size 269
#define meshtastic_DeviceMetadata_size 54
+#define meshtastic_DuplicatedPublicKey_size 0
#define meshtastic_FileInfo_size 236
#define meshtastic_FromRadio_size 510
#define meshtastic_Heartbeat_size 0
@@ -1913,6 +1959,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
#define meshtastic_KeyVerificationNumberRequest_size 52
#define meshtastic_KeyVerification_size 79
#define meshtastic_LogRecord_size 426
+#define meshtastic_LowEntropyKey_size 0
#define meshtastic_MeshPacket_size 378
#define meshtastic_MqttClientProxyMessage_size 501
#define meshtastic_MyNodeInfo_size 77
diff --git a/src/mesh/wifi/WiFiAPClient.cpp b/src/mesh/wifi/WiFiAPClient.cpp
index 789f8ac44..945460c28 100644
--- a/src/mesh/wifi/WiFiAPClient.cpp
+++ b/src/mesh/wifi/WiFiAPClient.cpp
@@ -327,9 +327,15 @@ static void WiFiEvent(WiFiEvent_t event)
break;
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
LOG_INFO("Connected to access point");
+#ifdef WIFI_LED
+ digitalWrite(WIFI_LED, HIGH);
+#endif
break;
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
LOG_INFO("Disconnected from WiFi access point");
+#ifdef WIFI_LED
+ digitalWrite(WIFI_LED, LOW);
+#endif
if (!isReconnecting) {
WiFi.disconnect(false, true);
syslog.disable();
@@ -378,9 +384,15 @@ static void WiFiEvent(WiFiEvent_t event)
break;
case ARDUINO_EVENT_WIFI_AP_START:
LOG_INFO("WiFi access point started");
+#ifdef WIFI_LED
+ digitalWrite(WIFI_LED, HIGH);
+#endif
break;
case ARDUINO_EVENT_WIFI_AP_STOP:
LOG_INFO("WiFi access point stopped");
+#ifdef WIFI_LED
+ digitalWrite(WIFI_LED, LOW);
+#endif
break;
case ARDUINO_EVENT_WIFI_AP_STACONNECTED:
LOG_INFO("Client connected");
@@ -474,4 +486,4 @@ uint8_t getWifiDisconnectReason()
{
return wifiDisconnectReason;
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp
index 4005222dc..ea4c46949 100644
--- a/src/modules/AdminModule.cpp
+++ b/src/modules/AdminModule.cpp
@@ -7,6 +7,7 @@
#include "SPILock.h"
#include "meshUtils.h"
#include
+#include // for better whitespace handling
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_BLUETOOTH
#include "BleOta.h"
#endif
@@ -155,6 +156,28 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
*/
case meshtastic_AdminMessage_set_owner_tag:
LOG_DEBUG("Client set owner");
+ // Validate names
+ if (*r->set_owner.long_name) {
+ const char *start = r->set_owner.long_name;
+ // Skip all whitespace (space, tab, newline, etc)
+ while (*start && isspace((unsigned char)*start))
+ start++;
+ if (*start == '\0') {
+ LOG_WARN("Rejected long_name: must contain at least 1 non-whitespace character");
+ myReply = allocErrorResponse(meshtastic_Routing_Error_BAD_REQUEST, &mp);
+ break;
+ }
+ }
+ if (*r->set_owner.short_name) {
+ const char *start = r->set_owner.short_name;
+ while (*start && isspace((unsigned char)*start))
+ start++;
+ if (*start == '\0') {
+ LOG_WARN("Rejected short_name: must contain at least 1 non-whitespace character");
+ myReply = allocErrorResponse(meshtastic_Routing_Error_BAD_REQUEST, &mp);
+ break;
+ }
+ }
handleSetOwner(r->set_owner);
break;
@@ -1153,6 +1176,27 @@ void AdminModule::handleStoreDeviceUIConfig(const meshtastic_DeviceUIConfig &uic
void AdminModule::handleSetHamMode(const meshtastic_HamParameters &p)
{
+ // Validate ham parameters before setting since this would bypass validation in the owner struct
+ if (*p.call_sign) {
+ const char *start = p.call_sign;
+ // Skip all whitespace
+ while (*start && isspace((unsigned char)*start))
+ start++;
+ if (*start == '\0') {
+ LOG_WARN("Rejected ham call_sign: must contain at least 1 non-whitespace character");
+ return;
+ }
+ }
+ if (*p.short_name) {
+ const char *start = p.short_name;
+ while (*start && isspace((unsigned char)*start))
+ start++;
+ if (*start == '\0') {
+ LOG_WARN("Rejected ham short_name: must contain at least 1 non-whitespace character");
+ return;
+ }
+ }
+
// Set call sign and override lora limitations for licensed use
strncpy(owner.long_name, p.call_sign, sizeof(owner.long_name));
strncpy(owner.short_name, p.short_name, sizeof(owner.short_name));
diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp
index dca8a3b44..894579a2f 100644
--- a/src/mqtt/MQTT.cpp
+++ b/src/mqtt/MQTT.cpp
@@ -763,7 +763,10 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp_encrypted, const meshtastic_Me
}
entry->topic = std::move(topic);
entry->envBytes.assign(bytes, numBytes);
- assert(mqttQueue.enqueue(entry, 0));
+ if (mqttQueue.enqueue(entry, 0) == false) {
+ LOG_CRIT("Failed to add a message to mqttQueue!");
+ abort();
+ }
}
}
diff --git a/src/nimble/NimbleBluetooth.cpp b/src/nimble/NimbleBluetooth.cpp
index 009439f25..177a07eb4 100644
--- a/src/nimble/NimbleBluetooth.cpp
+++ b/src/nimble/NimbleBluetooth.cpp
@@ -171,6 +171,11 @@ void NimbleBluetooth::deinit()
{
#ifdef ARCH_ESP32
LOG_INFO("Disable bluetooth until reboot");
+
+#ifdef BLE_LED
+ digitalWrite(BLE_LED, LOW);
+#endif
+
NimBLEDevice::deinit();
#endif
}
diff --git a/src/platform/esp32/main-esp32.cpp b/src/platform/esp32/main-esp32.cpp
index 3c4faac3e..cdea53c9a 100644
--- a/src/platform/esp32/main-esp32.cpp
+++ b/src/platform/esp32/main-esp32.cpp
@@ -56,9 +56,11 @@ void updateBatteryLevel(uint8_t level) {}
void getMacAddr(uint8_t *dmac)
{
#if defined(CONFIG_IDF_TARGET_ESP32C6) && defined(CONFIG_SOC_IEEE802154_SUPPORTED)
- assert(esp_base_mac_addr_get(dmac) == ESP_OK);
+ auto res = esp_base_mac_addr_get(dmac);
+ assert(res == ESP_OK);
#else
- assert(esp_efuse_mac_get_default(dmac) == ESP_OK);
+ auto res = esp_efuse_mac_get_default(dmac);
+ assert(res == ESP_OK);
#endif
}
diff --git a/src/platform/nrf52/architecture.h b/src/platform/nrf52/architecture.h
index eea3aee45..8ea2c3829 100644
--- a/src/platform/nrf52/architecture.h
+++ b/src/platform/nrf52/architecture.h
@@ -85,6 +85,8 @@
#define HW_VENDOR meshtastic_HardwareModel_SEEED_SOLAR_NODE
#elif defined(HELTEC_MESH_POCKET)
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_MESH_POCKET
+#elif defined(NOMADSTAR_METEOR_PRO)
+#define HW_VENDOR meshtastic_HardwareModel_NOMADSTAR_METEOR_PRO
#elif defined(SEEED_WIO_TRACKER_L1)
#define HW_VENDOR meshtastic_HardwareModel_SEEED_WIO_TRACKER_L1
#else
diff --git a/src/sleep.cpp b/src/sleep.cpp
index 8ffb08b04..6d1b2f348 100644
--- a/src/sleep.cpp
+++ b/src/sleep.cpp
@@ -332,7 +332,7 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false, bool skipSaveN
}
#endif
-#if defined(ARCH_ESP32) && defined(I2C_SDA)
+#if !MESHTASTIC_EXCLUDE_I2C && defined(ARCH_ESP32) && defined(I2C_SDA)
// Added by https://github.com/meshtastic/firmware/pull/4418
// Possibly to support Heltec Capsule Sensor?
Wire.end();
@@ -542,4 +542,4 @@ void enableLoraInterrupt()
}
#endif
}
-#endif
\ No newline at end of file
+#endif
diff --git a/userPrefs.jsonc b/userPrefs.jsonc
index a349a5700..497327478 100644
--- a/userPrefs.jsonc
+++ b/userPrefs.jsonc
@@ -21,6 +21,7 @@
// "USERPREFS_CONFIG_LORA_REGION": "meshtastic_Config_LoRaConfig_RegionCode_US",
// "USERPREFS_CONFIG_OWNER_LONG_NAME": "My Long Name",
// "USERPREFS_CONFIG_OWNER_SHORT_NAME": "MLN",
+ // "USERPREFS_CONFIG_DEVICE_ROLE": "meshtastic_Config_DeviceConfig_Role_CLIENT", // Defaults to CLIENT. ROUTER*, LOST AND FOUND, and REPEATER roles are restricted.
// "USERPREFS_EVENT_MODE": "1",
// "USERPREFS_FIXED_BLUETOOTH": "121212",
// "USERPREFS_FIXED_GPS": "",
diff --git a/variants/diy/hydra/variant.h b/variants/diy/hydra/variant.h
index 60bb60beb..4c809502e 100644
--- a/variants/diy/hydra/variant.h
+++ b/variants/diy/hydra/variant.h
@@ -8,7 +8,9 @@
#define PIN_GPS_EN 4
#define GPS_POWER_TOGGLE // Moved definition from platformio.ini to here
-#define BUTTON_PIN 39 // The middle button GPIO on the T-Beam
+#define BUTTON_PIN 39 // The middle button GPIO on the T-Beam
+// Note: On the ESP32 base version, gpio34-39 are input-only, and do not have internal pull-ups.
+// If 39 is not being used for a button, it is suggested to remove the #define.
#define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
#define ADC_CHANNEL ADC1_GPIO35_CHANNEL
#define ADC_MULTIPLIER 1.85 // (R1 = 470k, R2 = 680k)
diff --git a/variants/elecrow_panel/platformio.ini b/variants/elecrow_panel/platformio.ini
index 963174560..5bce58208 100644
--- a/variants/elecrow_panel/platformio.ini
+++ b/variants/elecrow_panel/platformio.ini
@@ -48,7 +48,7 @@ lib_deps = ${esp32s3_base.lib_deps}
lovyan03/LovyanGFX@1.2.0 ; note: v1.2.7 breaks the elecrow 7" display functionality
hideakitai/TCA9534@0.1.1
-[crowpanel_small] ; 2.4, 2.8, 3.5 inch
+[crowpanel_small_esp32s3_base] ; 2.4, 2.8, 3.5 inch
extends = crowpanel_base
build_flags =
${crowpanel_base.build_flags}
@@ -62,7 +62,7 @@ build_flags =
-D VIEW_320x240
-D MAP_FULL_REDRAW
-[crowpanel_large] ; 4.3, 5.0, 7.0 inch
+[crowpanel_large_esp32s3_base] ; 4.3, 5.0, 7.0 inch
extends = crowpanel_base
build_flags =
${crowpanel_base.build_flags}
@@ -73,9 +73,9 @@ build_flags =
-D DISPLAY_SET_RESOLUTION
[env:elecrow-adv-24-28-tft]
-extends = crowpanel_small
+extends = crowpanel_small_esp32s3_base
build_flags =
- ${crowpanel_small.build_flags}
+ ${crowpanel_small_esp32s3_base.build_flags}
-D SPI_FREQUENCY=80000000
-D LGFX_SCREEN_WIDTH=240
-D LGFX_SCREEN_HEIGHT=320
@@ -96,9 +96,9 @@ build_flags =
-D LGFX_TOUCH_ROTATION=0
[env:elecrow-adv-35-tft]
-extends = crowpanel_small
+extends = crowpanel_small_esp32s3_base
build_flags =
- ${crowpanel_small.build_flags}
+ ${crowpanel_small_esp32s3_base.build_flags}
-D LV_CACHE_DEF_SIZE=2097152
-D SPI_FREQUENCY=60000000
-D LGFX_SCREEN_WIDTH=320
@@ -122,7 +122,7 @@ build_flags =
; 4.3, 5.0, 7.0 inch 800x480 IPS (V1)
[env:elecrow-adv1-43-50-70-tft]
-extends = crowpanel_large
+extends = crowpanel_large_esp32s3_base
build_flags =
- ${crowpanel_large.build_flags}
+ ${crowpanel_large_esp32s3_base.build_flags}
-D VIEW_320x240
diff --git a/variants/heltec_wireless_bridge/platformio.ini b/variants/heltec_wireless_bridge/platformio.ini
index 45c3aba74..ab30eb744 100644
--- a/variants/heltec_wireless_bridge/platformio.ini
+++ b/variants/heltec_wireless_bridge/platformio.ini
@@ -3,4 +3,21 @@
extends = esp32_base
board = heltec_wifi_lora_32
build_flags =
- ${esp32_base.build_flags} -D HELTEC_WIRELESS_BRIDGE -I variants/heltec_wireless_bridge
\ No newline at end of file
+ ${esp32_base.build_flags}
+ -I variants/heltec_wireless_bridge
+ -D HELTEC_WIRELESS_BRIDGE
+ -D BOARD_HAS_PSRAM
+ -D RADIOLIB_EXCLUDE_LR11X0=1
+ -D RADIOLIB_EXCLUDE_SX128X=1
+ -D MESHTASTIC_EXCLUDE_CANNEDMESSAGES=1
+ -D MESHTASTIC_EXCLUDE_DETECTIONSENSOR=1
+ -D MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR=1
+ -D MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL=1
+ -D MESHTASTIC_EXCLUDE_EXTERNALNOTIFICATION=1
+ -D MESHTASTIC_EXCLUDE_GPS=1
+ -D MESHTASTIC_EXCLUDE_I2C=1
+ -D MESHTASTIC_EXCLUDE_INPUTBROKER=1
+ -D MESHTASTIC_EXCLUDE_POWER_FSM=1
+ -D MESHTASTIC_EXCLUDE_SERIAL=1
+ -D MESHTASTIC_EXCLUDE_SCREEN=1
+ -D MESHTASTIC_EXCLUDE_WAYPOINT=1
diff --git a/variants/heltec_wireless_bridge/variant.h b/variants/heltec_wireless_bridge/variant.h
index 7c4f41660..5ad16d0e2 100644
--- a/variants/heltec_wireless_bridge/variant.h
+++ b/variants/heltec_wireless_bridge/variant.h
@@ -1,29 +1,41 @@
-// the default ESP32 Pin of 15 is the Oled SCL, set to 36 and 37 and works fine.
-// Tested on Neo6m module.
+
+// updated variant 20250420 berlincount, tested with HTIT-TB
+//
+// connections in HTIT-WB
+// per https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf
+// md5: a0e6ae10ff76611aa61433366b2e4f5c esp32_datasheet_en.pdf
+// per https://resource.heltec.cn/download/Wireless_Bridge/Schematic_Diagram_HTIT-WB_V0.2.pdf
+// md5: d5c1b0219ece347dd8cee866d7d3ab0a Schematic_Diagram_HTIT-WB_V0.2.pdf
+
+#define NO_EXT_GPIO 1
+#define NO_GPS 1
+
+#define HAS_GPS 0 // GPS is not equipped
#undef GPS_RX_PIN
#undef GPS_TX_PIN
-#define GPS_RX_PIN 36
-#define GPS_TX_PIN 33
-#ifndef USE_JTAG // gpio15 is TDO for JTAG, so no I2C on this board while doing jtag
-#define I2C_SDA 4 // I2C pins for this board
-#define I2C_SCL 15
-#endif
-
-#define LED_PIN 25 // If defined we will blink this LED
-#define BUTTON_PIN 0 // If defined, this will be used for user button presses
+// Green / Lora = PIN 22 / GPIO2, Yellow / Wifi = PIN 23 / GPIO0, Blue / BLE = PIN 25 / GPIO16
+#define LED_PIN 22
+#define WIFI_LED 23
+#define BLE_LED 25
+// ESP32-D0WDQ6 direct pins SX1276
#define USE_RF95
-#define LORA_DIO0 26 // a No connect on the SX1262 module
-#ifndef USE_JTAG
-#define LORA_RESET 14
-#endif
+#define LORA_DIO0 26
#define LORA_DIO1 35
-#define LORA_DIO2 34 // Not really used
+#define LORA_DIO2 34
+#define LORA_SCK 05
+#define LORA_MISO 19
+#define LORA_MOSI 27
+#define LORA_CS 18
-// ratio of voltage divider = 3.20 (R1=100k, R2=220k)
-#define ADC_MULTIPLIER 3.2
+// several things are not possible with JTAG enabled
+#ifndef USE_JTAG
+#define LORA_RESET 14 // LoRa Reset shares a pin with MTMS
+#define I2C_SDA 4 // SD_DATA1 going to W25Q64, but
+#define I2C_SCL 15 // SD_CMD shared a pin with MTD0
+#endif
-#define BATTERY_PIN 13 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
-#define ADC_CHANNEL ADC2_GPIO13_CHANNEL
-#define BAT_MEASURE_ADC_UNIT 2
\ No newline at end of file
+// user button is present on device, but currently untested & unconfigured - couldn't figure out how it's connected
+
+// battery support is present within device, but currently untested & unconfigured - couldn't find reliable information yet
diff --git a/variants/rak4631_nomadstar_meteor_pro/platformio.ini b/variants/rak4631_nomadstar_meteor_pro/platformio.ini
new file mode 100644
index 000000000..d5fbe6a16
--- /dev/null
+++ b/variants/rak4631_nomadstar_meteor_pro/platformio.ini
@@ -0,0 +1,51 @@
+; NomadStar Meteor Pro based on RAK4631 with RGBW LED LP5562 support
+[env:rak4631_nomadstar_meteor_pro]
+extends = nrf52840_base
+board = wiscore_rak4631
+board_check = true
+build_flags = ${nrf52840_base.build_flags} -Ivariants/rak4631_nomadstar_meteor_pro -D NOMADSTAR_METEOR_PRO
+ -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard"
+ ;-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
+ -DEINK_DISPLAY_MODEL=GxEPD2_213_BN
+ -DEINK_WIDTH=250
+ -DEINK_HEIGHT=122
+ -DRADIOLIB_EXCLUDE_SX128X=1
+ -DRADIOLIB_EXCLUDE_SX127X=1
+ -DRADIOLIB_EXCLUDE_LR11X0=1
+build_src_filter = ${nrf52_base.build_src_filter} +<../variants/rak4631_nomadstar_meteor_pro> + +
+lib_deps =
+ ${nrf52840_base.lib_deps}
+ https://github.com/NomadStar-outdoor/IOBoard-RGB-LP5562-Library.git#9c366c8
+
+; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
+; Note: as of 6/2013 the serial/bootloader based programming takes approximately 30 seconds
+;upload_protocol = jlink
+
+; Allows programming and debug via the RAK NanoDAP as the default debugger tool for the RAK4631 (it is only $10!)
+; programming time is about the same as the bootloader version.
+; For information on this see the meshtastic developers documentation for "Development on the NRF52"
+[env:rak4631_nomadstar_meteor_pro_dbg]
+extends = env:rak4631_nomadstar_meteor_pro
+board_level = extra
+
+; if the builtin version of openocd has a buggy version of semihosting, so use the external version
+; platform_packages = platformio/tool-openocd@^3.1200.0
+
+build_flags =
+ ${env:rak4631.build_flags}
+ -D USE_SEMIHOSTING
+
+lib_deps =
+ ${env:rak4631.lib_deps}
+ https://github.com/geeksville/Armduino-Semihosting/archive/35b538fdf208c3530c1434cd099a08e486672ee4.zip
+
+; NOTE: the pyocd support for semihosting is buggy. So I switched to using the builtin platformio support for the stlink adapter which worked much better.
+; However the built in openocd version in platformio has buggy support for TCP to semihosting.
+;
+; So I'm now trying the external openocd - but the openocd scripts for nrf52.cfg assume you are using a DAP adapter not an STLINK adapter.
+; In theory I could change those scripts. But for now I'm trying going back to a DAP adapter but with the external openocd.
+
+upload_protocol = stlink
+; eventually use platformio/tool-pyocd@^2.3600.0 instad
+;upload_protocol = custom
+;upload_command = pyocd flash -t nrf52840 $UPLOADERFLAGS $SOURCE
\ No newline at end of file
diff --git a/variants/rak4631_nomadstar_meteor_pro/variant.cpp b/variants/rak4631_nomadstar_meteor_pro/variant.cpp
new file mode 100644
index 000000000..e84b60b3b
--- /dev/null
+++ b/variants/rak4631_nomadstar_meteor_pro/variant.cpp
@@ -0,0 +1,45 @@
+/*
+ Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+ Copyright (c) 2016 Sandeep Mistry All right reserved.
+ Copyright (c) 2018, Adafruit Industries (adafruit.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "variant.h"
+#include "nrf.h"
+#include "wiring_constants.h"
+#include "wiring_digital.h"
+
+const uint32_t g_ADigitalPinMap[] = {
+ // P0
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+
+ // P1
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
+
+void initVariant()
+{
+ // LED1 & LED2
+ pinMode(PIN_LED1, OUTPUT);
+ ledOff(PIN_LED1);
+
+ pinMode(PIN_LED2, OUTPUT);
+ ledOff(PIN_LED2);
+
+ // 3V3 Power Rail
+ pinMode(PIN_3V3_EN, OUTPUT);
+ digitalWrite(PIN_3V3_EN, HIGH);
+}
diff --git a/variants/rak4631_nomadstar_meteor_pro/variant.h b/variants/rak4631_nomadstar_meteor_pro/variant.h
new file mode 100644
index 000000000..51baf3ada
--- /dev/null
+++ b/variants/rak4631_nomadstar_meteor_pro/variant.h
@@ -0,0 +1,271 @@
+/*
+ Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+ Copyright (c) 2016 Sandeep Mistry All right reserved.
+ Copyright (c) 2018, Adafruit Industries (adafruit.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU Lesser General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef _VARIANT_RAK4630_
+#define _VARIANT_RAK4630_
+
+#define RAK4630
+
+/** Master clock frequency */
+#define VARIANT_MCK (64000000ul)
+
+#define USE_LFXO // Board uses 32khz crystal for LF
+// define USE_LFRC // Board uses RC for LF
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT (48)
+#define NUM_DIGITAL_PINS (48)
+#define NUM_ANALOG_INPUTS (6)
+#define NUM_ANALOG_OUTPUTS (0)
+
+// LEDs
+#define PIN_LED1 (35)
+#define PIN_LED2 (36)
+
+#define LED_BUILTIN PIN_LED1
+#define LED_CONN PIN_LED2
+
+#define LED_GREEN PIN_LED1
+#define LED_BLUE PIN_LED2
+
+#define LED_STATE_ON 1 // State when LED is litted
+
+/*
+ * Buttons
+ */
+
+#define PIN_BUTTON1 9 // Pin for button on E-ink button module or IO expansion
+#define BUTTON_NEED_PULLUP
+#define PIN_BUTTON2 12
+#define PIN_BUTTON3 24
+#define PIN_BUTTON4 25
+
+/*
+ * Analog pins
+ */
+#define PIN_A0 (5)
+#define PIN_A1 (31)
+#define PIN_A2 (28)
+#define PIN_A3 (29)
+#define PIN_A4 (30)
+#define PIN_A5 (31)
+#define PIN_A6 (0xff)
+#define PIN_A7 (0xff)
+
+static const uint8_t A0 = PIN_A0;
+static const uint8_t A1 = PIN_A1;
+static const uint8_t A2 = PIN_A2;
+static const uint8_t A3 = PIN_A3;
+static const uint8_t A4 = PIN_A4;
+static const uint8_t A5 = PIN_A5;
+static const uint8_t A6 = PIN_A6;
+static const uint8_t A7 = PIN_A7;
+#define ADC_RESOLUTION 14
+
+// Other pins
+#define PIN_AREF (2)
+#define PIN_NFC1 (9)
+#define PIN_NFC2 (10)
+
+static const uint8_t AREF = PIN_AREF;
+
+/*
+ * Serial interfaces
+ */
+#define PIN_SERIAL1_RX (15)
+#define PIN_SERIAL1_TX (16)
+
+// Connected to Jlink CDC
+#define PIN_SERIAL2_RX (8)
+#define PIN_SERIAL2_TX (6)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 2
+
+#define PIN_SPI_MISO (45)
+#define PIN_SPI_MOSI (44)
+#define PIN_SPI_SCK (43)
+
+#define PIN_SPI1_MISO (29) // (0 + 29)
+#define PIN_SPI1_MOSI (30) // (0 + 30)
+#define PIN_SPI1_SCK (3) // (0 + 3)
+
+static const uint8_t SS = 42;
+static const uint8_t MOSI = PIN_SPI_MOSI;
+static const uint8_t MISO = PIN_SPI_MISO;
+static const uint8_t SCK = PIN_SPI_SCK;
+
+/*
+ * eink display pins
+ */
+
+#define PIN_EINK_CS (0 + 26)
+#define PIN_EINK_BUSY (0 + 4)
+#define PIN_EINK_DC (0 + 17)
+#define PIN_EINK_RES (-1)
+#define PIN_EINK_SCLK (0 + 3)
+#define PIN_EINK_MOSI (0 + 30) // also called SDI
+
+// #define USE_EINK
+
+// Texas Instrument LP5562
+#define HAS_LP5562
+#define ENABLE_AMBIENTLIGHTING
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA (13)
+#define PIN_WIRE_SCL (14)
+
+// QSPI Pins
+#define PIN_QSPI_SCK 3
+#define PIN_QSPI_CS 26
+#define PIN_QSPI_IO0 30
+#define PIN_QSPI_IO1 29
+#define PIN_QSPI_IO2 28
+#define PIN_QSPI_IO3 2
+
+// On-board QSPI Flash
+#define EXTERNAL_FLASH_DEVICES IS25LP080D
+#define EXTERNAL_FLASH_USE_QSPI
+
+/* @note RAK5005-O GPIO mapping to RAK4631 GPIO ports
+ RAK5005-O <-> nRF52840
+ IO1 <-> P0.17 (Arduino GPIO number 17)
+ IO2 <-> P1.02 (Arduino GPIO number 34)
+ IO3 <-> P0.21 (Arduino GPIO number 21)
+ IO4 <-> P0.04 (Arduino GPIO number 4)
+ IO5 <-> P0.09 (Arduino GPIO number 9)
+ IO6 <-> P0.10 (Arduino GPIO number 10)
+ IO7 <-> P0.28 (Arduino GPIO number 28)
+ SW1 <-> P0.01 (Arduino GPIO number 1)
+ A0 <-> P0.04/AIN2 (Arduino Analog A2
+ A1 <-> P0.31/AIN7 (Arduino Analog A7
+ SPI_CS <-> P0.26 (Arduino GPIO number 26)
+ */
+
+// RAK4630 LoRa module
+
+/* Setup of the SX1262 LoRa module ( https://docs.rakwireless.com/Product-Categories/WisBlock/RAK4631/Datasheet/ )
+
+P1.10 NSS SPI NSS (Arduino GPIO number 42)
+P1.11 SCK SPI CLK (Arduino GPIO number 43)
+P1.12 MOSI SPI MOSI (Arduino GPIO number 44)
+P1.13 MISO SPI MISO (Arduino GPIO number 45)
+P1.14 BUSY BUSY signal (Arduino GPIO number 46)
+P1.15 DIO1 DIO1 event interrupt (Arduino GPIO number 47)
+P1.06 NRESET NRESET manual reset of the SX1262 (Arduino GPIO number 38)
+
+Important for successful SX1262 initialization:
+
+* Setup DIO2 to control the antenna switch
+* Setup DIO3 to control the TCXO power supply
+* Setup the SX1262 to use it's DCDC regulator and not the LDO
+* RAK4630 schematics show GPIO P1.07 connected to the antenna switch, but it should not be initialized, as DIO2 will do the
+control of the antenna switch
+
+SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG
+
+*/
+
+#define DETECTION_SENSOR_EN 4
+
+#define USE_SX1262
+#define SX126X_CS (42)
+#define SX126X_DIO1 (47)
+#define SX126X_BUSY (46)
+#define SX126X_RESET (38)
+// #define SX126X_TXEN (39)
+// #define SX126X_RXEN (37)
+#define SX126X_POWER_EN (37)
+// DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
+#define SX126X_DIO2_AS_RF_SWITCH
+#define SX126X_DIO3_TCXO_VOLTAGE 1.8
+
+// Testing USB detection
+#define NRF_APM
+
+// enables 3.3V periphery like GPS or IO Module
+// Do not toggle this for GPS power savings
+#define PIN_3V3_EN (34)
+
+// RAK1910 GPS module
+// If using the wisblock GPS module and pluged into Port A on WisBlock base
+// IO1 is hooked to PPS (pin 12 on header) = gpio 17
+// IO2 is hooked to GPS RESET = gpio 34, but it can not be used to this because IO2 is ALSO used to control 3V3_S power (1 is on).
+// Therefore must be 1 to keep peripherals powered
+// Power is on the controllable 3V3_S rail
+// #define PIN_GPS_RESET (34)
+// #define PIN_GPS_EN PIN_3V3_EN
+#define PIN_GPS_PPS (17) // Pulse per second input from the GPS
+
+#define GPS_RX_PIN PIN_SERIAL1_RX
+#define GPS_TX_PIN PIN_SERIAL1_TX
+
+// Define pin to enable GPS toggle (set GPIO to LOW) via user button triple press
+
+// RAK18001 Buzzer in Slot C
+// #define PIN_BUZZER 21 // IO3 is PWM2
+// NEW: set this via protobuf instead!
+
+// Battery
+// The battery sense is hooked to pin A0 (5)
+#define BATTERY_PIN PIN_A0
+// and has 12 bit resolution
+#define BATTERY_SENSE_RESOLUTION_BITS 12
+#define BATTERY_SENSE_RESOLUTION 4096.0
+#undef AREF_VOLTAGE
+#define AREF_VOLTAGE 3.0
+#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
+#define ADC_MULTIPLIER 1.73
+
+#define HAS_RTC 0
+
+#define HAS_ETHERNET 0
+
+#define RAK_4631 1
+
+#define PIN_ETHERNET_RESET 21
+#define PIN_ETHERNET_SS PIN_EINK_CS
+#define ETH_SPI_PORT SPI1
+#define AQ_SET_PIN 10
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ * Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#endif
\ No newline at end of file
diff --git a/variants/seeed_xiao_nrf52840_kit/variant.h b/variants/seeed_xiao_nrf52840_kit/variant.h
index e6ef74e2e..5d45d6ea1 100644
--- a/variants/seeed_xiao_nrf52840_kit/variant.h
+++ b/variants/seeed_xiao_nrf52840_kit/variant.h
@@ -142,7 +142,6 @@ static const uint8_t SCL = PIN_WIRE_SCL;
#define PIN_GPS_RX D6
#define PIN_GPS_TX D7
#define HAS_GPS 1
-#define GPS_BAUDRATE 9600
#define GPS_THREAD_INTERVAL 50
#define PIN_SERIAL1_RX PIN_GPS_TX
#define PIN_SERIAL1_TX PIN_GPS_RX
diff --git a/variants/t-deck/platformio.ini b/variants/t-deck/platformio.ini
index 14fbee6cf..0e644001e 100644
--- a/variants/t-deck/platformio.ini
+++ b/variants/t-deck/platformio.ini
@@ -67,7 +67,9 @@ build_flags =
; -D USE_DOUBLE_BUFFER
-D USE_PACKET_API
-D MAP_FULL_REDRAW
+ -D CUSTOM_TOUCH_DRIVER
lib_deps =
${env:t-deck.lib_deps}
${device-ui_base.lib_deps}
+ https://github.com/bitbank2/bb_captouch/archive/refs/tags/1.3.1.zip