From 4c162d35766c6904ccd1242409a812859d1feaa0 Mon Sep 17 00:00:00 2001 From: Miguel Fuertes Date: Tue, 21 Oct 2025 20:56:15 +0200 Subject: [PATCH] Add battery monitoring and LED control features for M9S device --- diffconfig_m9s | 3 + ...m64-dts-qcom-add-msm8916-generic-m9s.patch | 10 +- packages/configs-mf68e/files/rc.button.power | 13 -- packages/ledcontrol/Makefile | 10 +- packages/ledcontrol/files/50-battery-show | 16 +++ packages/ledcontrol/files/99-modem-led | 2 + .../ledcontrol/files/battery-monitor.init | 101 +++++++++++++ packages/ledcontrol/files/ledcontrol | 87 ----------- packages/ledcontrol/files/ledcontrol.sh | 136 ++++++++++++++++++ 9 files changed, 275 insertions(+), 103 deletions(-) create mode 100644 packages/ledcontrol/files/50-battery-show create mode 100644 packages/ledcontrol/files/battery-monitor.init delete mode 100644 packages/ledcontrol/files/ledcontrol create mode 100644 packages/ledcontrol/files/ledcontrol.sh diff --git a/diffconfig_m9s b/diffconfig_m9s index 3664dda..d986a7c 100644 --- a/diffconfig_m9s +++ b/diffconfig_m9s @@ -15,6 +15,8 @@ CONFIG_PACKAGE_bash=y CONFIG_PACKAGE_cgi-io=y CONFIG_PACKAGE_dbus=y CONFIG_PACKAGE_glib2=y +CONFIG_PACKAGE_inotifywait=y +CONFIG_PACKAGE_inotifywatch=y CONFIG_PACKAGE_ip-tiny=y CONFIG_PACKAGE_kmod-crypto-kpp=y CONFIG_PACKAGE_kmod-crypto-lib-chacha20=y @@ -30,6 +32,7 @@ CONFIG_PACKAGE_libdbus=y CONFIG_PACKAGE_libexpat=y CONFIG_PACKAGE_libfdisk=y CONFIG_PACKAGE_libffi=y +CONFIG_PACKAGE_libinotifytools=y CONFIG_PACKAGE_libiwinfo=y CONFIG_PACKAGE_libiwinfo-data=y CONFIG_PACKAGE_liblua=y diff --git a/msm89xx/patches-6.12/805-arm64-dts-qcom-add-msm8916-generic-m9s.patch b/msm89xx/patches-6.12/805-arm64-dts-qcom-add-msm8916-generic-m9s.patch index f8bcc5b..d303884 100644 --- a/msm89xx/patches-6.12/805-arm64-dts-qcom-add-msm8916-generic-m9s.patch +++ b/msm89xx/patches-6.12/805-arm64-dts-qcom-add-msm8916-generic-m9s.patch @@ -1,6 +1,6 @@ --- /dev/null +++ b/arch/arm64/boot/dts/qcom/msm8916-generic-m9s.dts -@@ -0,0 +1,118 @@ +@@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/dts-v1/; @@ -119,3 +119,11 @@ +&gpio_leds_default { + pins = "gpio0", "gpio1", "gpio72", "gpio73", "gpio84", "gpio85"; +}; ++ ++&pm8916_0 { ++ pon@800 { ++ watchdog { ++ status = "disabled"; ++ }; ++ }; ++}; diff --git a/packages/configs-mf68e/files/rc.button.power b/packages/configs-mf68e/files/rc.button.power index 237b1bd..3a523e8 100644 --- a/packages/configs-mf68e/files/rc.button.power +++ b/packages/configs-mf68e/files/rc.button.power @@ -9,22 +9,9 @@ lockfile="/tmp/toff.lock" delay=1 -maybe_notify_display_shutdown() { - . /lib/functions.sh - config_load system - config_get FIFO display fifo "/var/run/display.fifo" - - [ -p "$FIFO" ] && { - echo "shutdown" > "$FIFO" 2>/dev/null; - sleep 1; - } -} - shutdown() { logger -t poweroff "Powering off..." - # maybe_notify_display_shutdown - sync /sbin/poweroff } diff --git a/packages/ledcontrol/Makefile b/packages/ledcontrol/Makefile index 5112cfb..a599bd9 100644 --- a/packages/ledcontrol/Makefile +++ b/packages/ledcontrol/Makefile @@ -11,7 +11,7 @@ define Package/ledcontrol SECTION:=utils CATEGORY:=Utilities TITLE:=Simple LED control utility - DEPENDS:= + DEPENDS:=+kmod-button-hotplug +inotifywait endef define Package/ledcontrol/description @@ -25,13 +25,19 @@ endef define Package/ledcontrol/install $(INSTALL_DIR) $(1)/usr/sbin - $(INSTALL_BIN) ./files/ledcontrol $(1)/usr/sbin/ + $(INSTALL_BIN) ./files/ledcontrol.sh $(1)/usr/sbin/ $(INSTALL_DIR) $(1)/etc/hotplug.d/ieee80211 $(INSTALL_DATA) ./files/99-wifi-led $(1)/etc/hotplug.d/ieee80211/ $(INSTALL_DIR) $(1)/etc/hotplug.d/iface $(INSTALL_DATA) ./files/99-modem-led $(1)/etc/hotplug.d/iface/ + + $(INSTALL_DIR) $(1)/etc/hotplug.d/button + $(INSTALL_DATA) ./files/50-battery-show $(1)/etc/hotplug.d/button/ + + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_DATA) ./files/battery-monitor.init $(1)/etc/init.d/battery-monitor endef $(eval $(call BuildPackage,ledcontrol)) diff --git a/packages/ledcontrol/files/50-battery-show b/packages/ledcontrol/files/50-battery-show new file mode 100644 index 0000000..79370a8 --- /dev/null +++ b/packages/ledcontrol/files/50-battery-show @@ -0,0 +1,16 @@ +#!/bin/sh +# /etc/hotplug.d/button/50-battery-show + +[ "$BUTTON" = "power" ] || exit 0 +[ "$ACTION" = "pressed" ] || exit 0 + +# Solo actuar si NO está cargando +charging=$(cat /sys/class/power_supply/pm8916-lbc-chgr/online 2>/dev/null || echo 0) + +if [ "$charging" = "0" ]; then + # Enviar SIGUSR1 al daemon para mostrar batería + [ -f /var/run/battery-monitor.pid ] && { + kill -USR1 $(cat /var/run/battery-monitor.pid) 2>/dev/null + logger -t button-battery "SIGUSR1 sent to battery-monitor" + } +fi diff --git a/packages/ledcontrol/files/99-modem-led b/packages/ledcontrol/files/99-modem-led index dbc0a88..b155a5c 100644 --- a/packages/ledcontrol/files/99-modem-led +++ b/packages/ledcontrol/files/99-modem-led @@ -4,10 +4,12 @@ case "$ACTION:$INTERFACE" in ifup:modem) + ledcontrol wan red off 2>/dev/null || true ledcontrol wan on logger -t modem-led "Modem UP - Green LED ON" ;; ifdown:modem) + ledcontrol wan red on 2>/dev/null || true ledcontrol wan off logger -t modem-led "Modem DOWN - Green LED OFF" ;; diff --git a/packages/ledcontrol/files/battery-monitor.init b/packages/ledcontrol/files/battery-monitor.init new file mode 100644 index 0000000..79e6847 --- /dev/null +++ b/packages/ledcontrol/files/battery-monitor.init @@ -0,0 +1,101 @@ +#!/bin/sh /etc/rc.common +# /etc/init.d/battery-monitor + +START=99 +STOP=01 + +CHARGER_FILE="/sys/class/power_supply/pm8916-lbc-chgr/online" +BMS_PATH="/sys/class/power_supply/pm8916-bms-vm" + +get_capacity() { + local voltage=$(cat $BMS_PATH/voltage_now 2>/dev/null) + local vmax=$(cat $BMS_PATH/voltage_max_design 2>/dev/null) + local vmin=$(cat $BMS_PATH/voltage_min_design 2>/dev/null) + + if [ -n "$voltage" ] && [ -n "$vmax" ] && [ -n "$vmin" ]; then + awk -v v="$voltage" -v vmax="$vmax" -v vmin="$vmin" \ + 'BEGIN {pct = ((v - vmin) / (vmax - vmin)) * 100; + if (pct < 0) pct = 0; + if (pct > 100) pct = 100; + printf "%.0f", pct}' + else + echo "50" + fi +} + +show_battery_temp() { + local capacity=$(get_capacity) + + ledcontrol charging red off 2>/dev/null + ledcontrol charging green off 2>/dev/null + + if [ "$capacity" -lt 20 ]; then + ledcontrol charging red on 2>/dev/null + elif [ "$capacity" -lt 50 ]; then + ledcontrol charging red on 2>/dev/null + ledcontrol charging green on 2>/dev/null + else + ledcontrol charging green on 2>/dev/null + fi + + logger -t battery-monitor "SIGUSR1: Showing ${capacity}%" + + sleep 2 + + update_led +} + +update_led() { + local charging=$(cat $CHARGER_FILE 2>/dev/null || echo 0) + + if [ "$charging" = "1" ]; then + local capacity=$(get_capacity) + + ledcontrol charging red off 2>/dev/null + ledcontrol charging green off 2>/dev/null + + if [ "$capacity" -ge 95 ]; then + ledcontrol charging green on 2>/dev/null + logger -t battery-monitor "Charging complete: ${capacity}%" + elif [ "$capacity" -ge 50 ]; then + ledcontrol charging red blink 2>/dev/null & + ledcontrol charging green blink 2>/dev/null & + logger -t battery-monitor "Charging: ${capacity}%" + else + ledcontrol charging red blink 2>/dev/null + logger -t battery-monitor "Charging low: ${capacity}%" + fi + else + ledcontrol charging red off 2>/dev/null + ledcontrol charging green off 2>/dev/null + fi +} + +start() { + update_led + + ( + trap 'show_battery_temp' USR1 + + while true; do + inotifywait -qq -e modify $CHARGER_FILE 2>/dev/null + sleep 1 + update_led + done + ) & + + echo $! > /var/run/battery-monitor.pid +} + +stop() { + [ -f /var/run/battery-monitor.pid ] && { + kill $(cat /var/run/battery-monitor.pid) 2>/dev/null + rm -f /var/run/battery-monitor.pid + } + + ledcontrol charging red blink 2>/dev/null + ledcontrol charging green blink 2>/dev/null + + logger -t shutdown-led "BAT LED blinking amber - shutdown" + return 0 +} diff --git a/packages/ledcontrol/files/ledcontrol b/packages/ledcontrol/files/ledcontrol deleted file mode 100644 index 68e338a..0000000 --- a/packages/ledcontrol/files/ledcontrol +++ /dev/null @@ -1,87 +0,0 @@ -#!/bin/sh -# LED Control Utility for OpenWrt -# Usage: ledcontrol - -set -e - -COLOR="$1" -ACTION="$2" - -# LED base path -LED_BASE="/sys/class/leds" - -# Find LED by color -find_led() { - local color="$1" - local led_path - - # Search for LED containing the color in name - led_path=$(find "$LED_BASE" -maxdepth 1 -type l -iname "*:${color}:*" 2>/dev/null | head -n 1) - - if [ -z "$led_path" ]; then - # Try without colons - led_path=$(find "$LED_BASE" -maxdepth 1 -type l -iname "*${color}*" 2>/dev/null | head -n 1) - fi - - if [ -z "$led_path" ]; then - logger -t ledcontrol "LED color '$color' not found" - echo "[!] LED color '$color' not found" >&2 - echo "[*] Available LEDs:" >&2 - ls -1 "$LED_BASE" | sed 's/^/ /' >&2 - return 1 - fi - - echo "$led_path" -} - -# Set LED state -set_led() { - local led_path="$1" - local action="$2" - - case "$action" in - on) - echo none > "$led_path/trigger" - echo 1 > "$led_path/brightness" - ;; - off) - echo none > "$led_path/trigger" - echo 0 > "$led_path/brightness" - ;; - blink) - echo timer > "$led_path/trigger" - echo 500 > "$led_path/delay_on" - echo 500 > "$led_path/delay_off" - ;; - blink_fast) - echo timer > "$led_path/trigger" - echo 100 > "$led_path/delay_on" - echo 100 > "$led_path/delay_off" - ;; - *) - logger -t ledcontrol "Invalid action: $action" - echo "[!] Invalid action: $action" >&2 - echo "[*] Valid actions: on, off, blink, blink_fast" >&2 - return 1 - ;; - esac -} - -# Main -if [ -z "$COLOR" ] || [ -z "$ACTION" ]; then - echo "Usage: ledcontrol " >&2 - echo "" >&2 - echo "Available LEDs:" >&2 - ls -1 "$LED_BASE" 2>/dev/null | sed 's/^/ /' >&2 - exit 1 -fi - -LED_PATH=$(find_led "$COLOR") || exit 1 -LED_NAME=$(basename "$LED_PATH") - -if set_led "$LED_PATH" "$ACTION"; then - logger -t ledcontrol "LED '$LED_NAME' set to '$ACTION'" - echo "[+] LED '$COLOR' set to '$ACTION'" -else - exit 1 -fi diff --git a/packages/ledcontrol/files/ledcontrol.sh b/packages/ledcontrol/files/ledcontrol.sh new file mode 100644 index 0000000..1091902 --- /dev/null +++ b/packages/ledcontrol/files/ledcontrol.sh @@ -0,0 +1,136 @@ +#!/bin/sh +# LED Control Utility for OpenWrt +# Usage: ledcontrol [color] +# Examples: +# ledcontrol wan on (MiFi with green:wan) +# ledcontrol wlan on (MiFi with green:wlan) +# ledcontrol blue on (Dongle with blue LED) +# ledcontrol wan green on (Explicit color override) + +set -e + +# Parse arguments (support both 2 and 3 arg syntax) +if [ $# -eq 2 ]; then + # 2 args: + SEARCH_KEY="$1" + COLOR="" + ACTION="$2" +elif [ $# -eq 3 ]; then + # 3 args: + SEARCH_KEY="$1" + COLOR="$2" + ACTION="$3" +else + echo "Usage: ledcontrol " >&2 + echo " or: ledcontrol " >&2 + echo "" >&2 + echo "Examples:" >&2 + echo " ledcontrol wan on # Auto-detect color (green:wan or blue)" >&2 + echo " ledcontrol wlan off # Auto-detect color (green:wlan or blue)" >&2 + echo " ledcontrol blue blink # Specific color LED" >&2 + echo " ledcontrol wan green on # Explicit function+color" >&2 + echo "" >&2 + echo "Available LEDs:" >&2 + ls -1 /sys/class/leds 2>/dev/null | grep -v "^mmc" | sed 's/^/ /' >&2 + exit 1 +fi + +LED_BASE="/sys/class/leds" + +# Find LED with smart matching +find_led() { + local search="$1" + local color="$2" + local led_path + + # Priority 1: Exact match with color prefix (green:wan, red:wlan) + if [ -n "$color" ]; then + led_path=$(find "$LED_BASE" -maxdepth 1 -type l -name "${color}:${search}" 2>/dev/null | head -n 1) + if [ -n "$led_path" ]; then + echo "$led_path" + return 0 + fi + fi + + # Priority 2: Function-based match (wan, wlan, charging) + # Prefer green for status, fallback to any color + for clr in green blue red amber; do + led_path=$(find "$LED_BASE" -maxdepth 1 -type l -name "${clr}:${search}" 2>/dev/null | head -n 1) + if [ -n "$led_path" ]; then + echo "$led_path" + return 0 + fi + done + + # Priority 3: Color-only match (blue, green, red) + led_path=$(find "$LED_BASE" -maxdepth 1 -type l -name "${search}" 2>/dev/null | head -n 1) + if [ -n "$led_path" ]; then + echo "$led_path" + return 0 + fi + + # Priority 4: Case-insensitive partial match + led_path=$(find "$LED_BASE" -maxdepth 1 -type l | grep -i "${search}" | grep -v "mmc" | head -n 1) + if [ -n "$led_path" ]; then + echo "$led_path" + return 0 + fi + + logger -t ledcontrol "LED '$search' not found" + echo "[!] LED '$search' not found" >&2 + echo "[*] Available LEDs:" >&2 + ls -1 "$LED_BASE" 2>/dev/null | grep -v "^mmc" | sed 's/^/ /' >&2 + return 1 +} + +# Set LED state +set_led() { + local led_path="$1" + local action="$2" + + case "$action" in + on) + echo none > "$led_path/trigger" 2>/dev/null || true + echo 1 > "$led_path/brightness" + ;; + off) + echo none > "$led_path/trigger" 2>/dev/null || true + echo 0 > "$led_path/brightness" + ;; + blink) + echo timer > "$led_path/trigger" 2>/dev/null || { + echo "[!] Blink not supported, setting ON" >&2 + echo 1 > "$led_path/brightness" + return 0 + } + echo 500 > "$led_path/delay_on" 2>/dev/null || true + echo 500 > "$led_path/delay_off" 2>/dev/null || true + ;; + blink_fast) + echo timer > "$led_path/trigger" 2>/dev/null || { + echo "[!] Blink not supported, setting ON" >&2 + echo 1 > "$led_path/brightness" + return 0 + } + echo 100 > "$led_path/delay_on" 2>/dev/null || true + echo 100 > "$led_path/delay_off" 2>/dev/null || true + ;; + *) + logger -t ledcontrol "Invalid action: $action" + echo "[!] Invalid action: $action" >&2 + echo "[*] Valid actions: on, off, blink, blink_fast" >&2 + return 1 + ;; + esac +} + +# Main +LED_PATH=$(find_led "$SEARCH_KEY" "$COLOR") || exit 1 +LED_NAME=$(basename "$LED_PATH") + +if set_led "$LED_PATH" "$ACTION"; then + logger -t ledcontrol "LED '$LED_NAME' set to '$ACTION'" + echo "[+] LED '$LED_NAME' set to '$ACTION'" +else + exit 1 +fi