Fix SIM2 QMI UIM provisioning, auto-enable ModemManager, PIN auto-prompt, call audio, and Dunst clearing
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
# Maximum time to wait for SIM card to appear after starting the modem.
|
# Maximum time to wait for SIM card to appear after starting the modem.
|
||||||
# Some SIM cards or modem firmwares might take longer to initialize.
|
# Some SIM cards or modem firmwares might take longer to initialize.
|
||||||
# Set to 0 to disable waiting entirely.
|
# Set to 0 to disable waiting entirely.
|
||||||
sim_wait_time=4
|
sim_wait_time=10
|
||||||
|
|
||||||
# Preferred physical SIM slot (1 or 2) for Primary GW provisioning on Dual-SIM
|
# Preferred physical SIM slot (1 or 2) for Primary GW provisioning on Dual-SIM
|
||||||
# Qualcomm MSM8905/MSM8909 devices. Falls back automatically if the preferred
|
# Qualcomm MSM8905/MSM8909 devices. Falls back automatically if the preferred
|
||||||
|
|||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
#!/sbin/openrc-run
|
||||||
|
|
||||||
|
# This script tries to automatically configure UIM application for Qualcomm QMI
|
||||||
|
# modems with more than one sim slot.
|
||||||
|
|
||||||
|
name="UIM Slot selection"
|
||||||
|
description="Select UIM slot and application on the embedded QMI modem."
|
||||||
|
|
||||||
|
depend() {
|
||||||
|
need rmtfs
|
||||||
|
after msm8909-modem-wwan-port
|
||||||
|
before ofono
|
||||||
|
before modemmanager
|
||||||
|
}
|
||||||
|
|
||||||
|
# Use the service start method instead of command= because we want to block
|
||||||
|
# other services while the modem isn't ready yet.
|
||||||
|
start() {
|
||||||
|
SIM_WAIT_TIME="${sim_wait_time:-10}" /usr/libexec/msm-modem-uim-selection boot
|
||||||
|
eend $?
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
horizontal_padding = 6
|
horizontal_padding = 6
|
||||||
frame_width = 2
|
frame_width = 2
|
||||||
frame_color = "#005577"
|
frame_color = "#005577"
|
||||||
idle_threshold = 120
|
idle_threshold = 0
|
||||||
font = Fira Code 9.5
|
font = Fira Code 9.5
|
||||||
markup = full
|
markup = full
|
||||||
max_icon_size = 24
|
max_icon_size = 24
|
||||||
@@ -22,16 +22,16 @@
|
|||||||
[urgency_low]
|
[urgency_low]
|
||||||
background = "#222222"
|
background = "#222222"
|
||||||
foreground = "#cccccc"
|
foreground = "#cccccc"
|
||||||
timeout = 8
|
timeout = 5
|
||||||
|
|
||||||
[urgency_normal]
|
[urgency_normal]
|
||||||
background = "#1c1c1c"
|
background = "#1c1c1c"
|
||||||
foreground = "#ffffff"
|
foreground = "#ffffff"
|
||||||
frame_color = "#005577"
|
frame_color = "#005577"
|
||||||
timeout = 12
|
timeout = 8
|
||||||
|
|
||||||
[urgency_critical]
|
[urgency_critical]
|
||||||
background = "#900000"
|
background = "#900000"
|
||||||
foreground = "#ffffff"
|
foreground = "#ffffff"
|
||||||
frame_color = "#ff0000"
|
frame_color = "#ff0000"
|
||||||
timeout = 0
|
timeout = 10
|
||||||
|
|||||||
@@ -3,61 +3,42 @@
|
|||||||
# shellcheck source=scripts/core/sxmo_common.sh
|
# shellcheck source=scripts/core/sxmo_common.sh
|
||||||
. sxmo_common.sh
|
. sxmo_common.sh
|
||||||
|
|
||||||
ca_dbus_get_prop() {
|
|
||||||
dbus-send --session --print-reply --dest=org.mobian_project.CallAudio \
|
|
||||||
--reply-timeout=2500 /org/mobian_project/CallAudio org.freedesktop.DBus.Properties.Get \
|
|
||||||
string:org.mobian_project.CallAudio string:"$1"
|
|
||||||
}
|
|
||||||
|
|
||||||
ca_dbus_set_prop() {
|
|
||||||
dbus-send --session --print-reply --type=method_call \
|
|
||||||
--reply-timeout=2500 --dest=org.mobian_project.CallAudio \
|
|
||||||
/org/mobian_project/CallAudio org.mobian_project.CallAudio."$1" "$2" |\
|
|
||||||
grep -q "boolean true" && return 0 || return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
enable_call_audio_mode() {
|
enable_call_audio_mode() {
|
||||||
if pactl -f json info 2>/dev/null | jq -r .server_name | grep -q PipeWire; then
|
if command -v amixer >/dev/null 2>&1; then
|
||||||
sxmo_audio.sh device set Earpiece
|
amixer -c 0 sset 'PRI_MI2S_RX Voice Mixer VoiceMMode1' on >/dev/null 2>&1 || true
|
||||||
sxmo_log "Successfully enabled call audio mode (Earpiece)."
|
amixer -c 0 sset 'VoiceMMode1 Capture Mixer TERT_MI2S_TX' on >/dev/null 2>&1 || true
|
||||||
sxmo_hook_statusbar.sh volume
|
amixer -c 0 sset 'RX1 MIX1 INP1' 'RX1' >/dev/null 2>&1 || true
|
||||||
return 0
|
amixer -c 0 sset 'RDAC2 MUX' 'RX1' >/dev/null 2>&1 || true
|
||||||
fi
|
amixer -c 0 sset 'EAR_S' 'Switch' >/dev/null 2>&1 || true
|
||||||
if ca_dbus_set_prop SelectMode uint32:1; then
|
amixer -c 0 sset 'DEC1 MUX' 'ADC1' >/dev/null 2>&1 || true
|
||||||
sxmo_log "Successfully enabled call audio mode."
|
amixer -c 0 sset 'ADC1 Volume' 100% >/dev/null 2>&1 || true
|
||||||
sxmo_hook_statusbar.sh volume
|
amixer -c 0 sset 'RX1 Digital Volume' 84 >/dev/null 2>&1 || true
|
||||||
else
|
fi
|
||||||
sxmo_notify_user.sh "Failed to enable call audio mode."
|
sxmo_audio.sh device set Earpiece >/dev/null 2>&1 || true
|
||||||
return 1
|
sxmo_log "Enabled ALSA voice call audio mode (Earpiece)."
|
||||||
fi
|
sxmo_hook_statusbar.sh volume >/dev/null 2>&1 || true
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
disable_call_audio_mode() {
|
disable_call_audio_mode() {
|
||||||
if pactl -f json info 2>/dev/null | jq -r .server_name | grep -q PipeWire; then
|
if command -v amixer >/dev/null 2>&1; then
|
||||||
sxmo_audio.sh device set Speaker
|
amixer -c 0 sset 'PRI_MI2S_RX Voice Mixer VoiceMMode1' off >/dev/null 2>&1 || true
|
||||||
sxmo_log "Successfully disabled call audio mode (Speaker)."
|
amixer -c 0 sset 'VoiceMMode1 Capture Mixer TERT_MI2S_TX' off >/dev/null 2>&1 || true
|
||||||
sxmo_hook_statusbar.sh volume
|
fi
|
||||||
return 0
|
sxmo_audio.sh device set Speaker >/dev/null 2>&1 || true
|
||||||
fi
|
sxmo_log "Disabled ALSA voice call audio mode (Speaker)."
|
||||||
if ca_dbus_set_prop SelectMode uint32:0; then
|
sxmo_hook_statusbar.sh volume >/dev/null 2>&1 || true
|
||||||
sxmo_log "Successfully disabled call audio mode."
|
return 0
|
||||||
sxmo_hook_statusbar.sh volume
|
|
||||||
else
|
|
||||||
sxmo_notify_user.sh "Failed to disable call audio mode."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_audio() {
|
setup_audio() {
|
||||||
if ! enable_call_audio_mode; then
|
enable_call_audio_mode
|
||||||
return 1
|
return 0
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reset_audio() {
|
reset_audio() {
|
||||||
if ! disable_call_audio_mode; then
|
disable_call_audio_mode
|
||||||
return 1
|
return 0
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"$@"
|
"$@"
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ pickup() {
|
|||||||
NUM="$(vid_to_number "$CALLID" 2>/dev/null || true)"
|
NUM="$(vid_to_number "$CALLID" 2>/dev/null || true)"
|
||||||
|
|
||||||
DIRECTION="$(
|
DIRECTION="$(
|
||||||
mmcli --voice-status -o "$CALLID" -K |
|
(mmcli -m any -o "$CALLID" -K 2>/dev/null || mmcli -o "$CALLID" -K 2>/dev/null || mmcli --voice-status -o "$CALLID" -K 2>/dev/null) |
|
||||||
grep call.properties.direction |
|
grep call.properties.direction |
|
||||||
cut -d: -f2 |
|
cut -d: -f2 |
|
||||||
tr -d " "
|
tr -d " "
|
||||||
@@ -53,11 +53,12 @@ pickup() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sxmo_notify_user.sh "Started call"
|
|
||||||
touch "$XDG_RUNTIME_DIR/sxmo_calls/${CALLID}.initiatedcall"
|
touch "$XDG_RUNTIME_DIR/sxmo_calls/${CALLID}.initiatedcall"
|
||||||
log_event "call_start" "$CALLID"
|
log_event "call_start" "$CALLID"
|
||||||
if command -v xcallscreen >/dev/null 2>&1; then
|
if command -v xcallscreen >/dev/null 2>&1; then
|
||||||
xcallscreen outgoing "$CALLID" "$NUM" >/dev/null 2>&1 || true
|
xcallscreen outgoing "$CALLID" "$NUM" >/dev/null 2>&1 || true
|
||||||
|
else
|
||||||
|
sxmo_notify_user.sh "Started call"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
incoming)
|
incoming)
|
||||||
@@ -74,11 +75,12 @@ pickup() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sxmo_notify_user.sh "Picked up call"
|
|
||||||
touch "$XDG_RUNTIME_DIR/sxmo_calls/${CALLID}.pickedupcall"
|
touch "$XDG_RUNTIME_DIR/sxmo_calls/${CALLID}.pickedupcall"
|
||||||
log_event "call_pickup" "$CALLID"
|
log_event "call_pickup" "$CALLID"
|
||||||
if command -v xcallscreen >/dev/null 2>&1; then
|
if command -v xcallscreen >/dev/null 2>&1; then
|
||||||
xcallscreen active "$CALLID" "$NUM" >/dev/null 2>&1 || true
|
xcallscreen active "$CALLID" "$NUM" >/dev/null 2>&1 || true
|
||||||
|
else
|
||||||
|
sxmo_notify_user.sh "Picked up call"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
|||||||
@@ -16,15 +16,16 @@ dial_number() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
NUMBER="$1"
|
NUMBER="$(printf "%s" "$1" | tr -cd '+0-9*#')"
|
||||||
|
if [ -z "$NUMBER" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
CLEANEDNUMBER="$(pnc find ${DEFAULT_COUNTRY:+-c "$DEFAULT_COUNTRY"} "$1" 2>/dev/null || true)"
|
mm_state="$(mmcli -m any -K 2>/dev/null | awk -F': ' '$1 == "modem.generic.state" {print $2; exit}')"
|
||||||
if [ -n "$CLEANEDNUMBER" ] && [ "$NUMBER" != "$CLEANEDNUMBER" ]; then
|
if [ "$mm_state" = "disabled" ] || [ -z "$mm_state" ]; then
|
||||||
NUMBER="$(cat <<EOF | sxmo_dmenu.sh -p "Rewrite ?"
|
mmcli -m any -e >/dev/null 2>&1 || true
|
||||||
$NUMBER
|
mmcli -m any --3gpp-register-home >/dev/null 2>&1 || true
|
||||||
$CLEANEDNUMBER
|
sleep 1
|
||||||
EOF
|
|
||||||
)"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sxmo_log "Attempting to dial: $NUMBER"
|
sxmo_log "Attempting to dial: $NUMBER"
|
||||||
@@ -33,7 +34,7 @@ EOF
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if ! CALLID="$(
|
if ! CALLID="$(
|
||||||
mmcli -m any --voice-create-call "number=$NUMBER" |
|
mmcli -m any --voice-create-call="number=$NUMBER" 2>/dev/null |
|
||||||
grep -Eo "Call/[0-9]+" |
|
grep -Eo "Call/[0-9]+" |
|
||||||
grep -oE "[0-9]+"
|
grep -oE "[0-9]+"
|
||||||
)"; then
|
)"; then
|
||||||
@@ -79,16 +80,22 @@ EOF
|
|||||||
}
|
}
|
||||||
|
|
||||||
dial_ussd() {
|
dial_ussd() {
|
||||||
|
|
||||||
USSD="$1"
|
USSD="$1"
|
||||||
DBUS_MODEM=$(mmcli -J -L | jq -r '."modem-list"[]')
|
|
||||||
MM_BUS="org.freedesktop.ModemManager1"
|
|
||||||
USSD_IFACE="org.freedesktop.ModemManager1.Modem.Modem3gpp.Ussd"
|
|
||||||
|
|
||||||
sxmo_log "Dialling USSD: $USSD"
|
sxmo_log "Dialling USSD: $USSD"
|
||||||
OUTPUT=$(busctl --json=short call "$MM_BUS" "$DBUS_MODEM" "$USSD_IFACE" Initiate "s" "$USSD" | jq -r '.data[]')
|
OUTPUT="$(doas -n /usr/libexec/msm-modem-uim-selection ussd initiate "$USSD" 2>/dev/null || /usr/libexec/msm-modem-uim-selection ussd initiate "$USSD" 2>/dev/null || true)"
|
||||||
|
if [ -z "$OUTPUT" ]; then
|
||||||
sxmo_terminal.sh sxmo_ussd.sh "$DBUS_MODEM" "Unknown" "$OUTPUT" &
|
DBUS_MODEM="$(mmcli -J -L 2>/dev/null | jq -r '."modem-list"[]' 2>/dev/null | head -n1)"
|
||||||
|
MM_BUS="org.freedesktop.ModemManager1"
|
||||||
|
USSD_IFACE="org.freedesktop.ModemManager1.Modem.Modem3gpp.Ussd"
|
||||||
|
if [ -n "$DBUS_MODEM" ]; then
|
||||||
|
OUTPUT="$(busctl --json=short call "$MM_BUS" "$DBUS_MODEM" "$USSD_IFACE" Initiate "s" "$USSD" 2>/dev/null | jq -r '.data[]' 2>/dev/null || true)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ -n "$OUTPUT" ]; then
|
||||||
|
sxmo_notify_user.sh "USSD ($USSD): $OUTPUT"
|
||||||
|
else
|
||||||
|
sxmo_notify_user.sh --urgency=critical "USSD request failed ($USSD)"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
dial_menu() {
|
dial_menu() {
|
||||||
|
|||||||
Executable
+174
@@ -0,0 +1,174 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
# Copyright 2022 Sxmo Contributors
|
||||||
|
|
||||||
|
# include common definitions
|
||||||
|
# shellcheck source=scripts/core/sxmo_common.sh
|
||||||
|
. sxmo_common.sh
|
||||||
|
|
||||||
|
# see networkmanager documentation for these state names
|
||||||
|
statenumtoname() {
|
||||||
|
case "$1" in
|
||||||
|
"int32 -1") printf "failed" ;;
|
||||||
|
"int32 0") printf "unknown" ;;
|
||||||
|
"int32 1") printf "initializing" ;;
|
||||||
|
"int32 2") printf "locked" ;;
|
||||||
|
"int32 3") printf "disabled" ;;
|
||||||
|
"int32 4") printf "disabling" ;;
|
||||||
|
"int32 5") printf "enabling" ;;
|
||||||
|
"int32 6") printf "enabled" ;;
|
||||||
|
"int32 7") printf "searching" ;;
|
||||||
|
"int32 8") printf "registered" ;;
|
||||||
|
"int32 9") printf "disconnecting" ;;
|
||||||
|
"int32 10") printf "connecting" ;;
|
||||||
|
"int32 11") printf "connected" ;;
|
||||||
|
*) printf "ERROR" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
mainloop() {
|
||||||
|
# get initial modem state and handle SIM2/QMI PIN lock or unprovisioned slot
|
||||||
|
(
|
||||||
|
tries=0
|
||||||
|
newstate=""
|
||||||
|
while [ "$tries" -lt 15 ]; do
|
||||||
|
newstate="$(mmcli -m any -K 2>/dev/null | grep "^modem.generic.state " | cut -d':' -f2 | sed 's/^ //')"
|
||||||
|
if [ -n "$newstate" ]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 2
|
||||||
|
tries=$((tries + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
uim_st="$(doas -n /usr/libexec/msm-modem-uim-selection status 2>/dev/null || /usr/libexec/msm-modem-uim-selection status 2>/dev/null || true)"
|
||||||
|
if printf "%s\n" "$uim_st" | grep -qE "SLOT[12]_PIN1_STATE=(enabled-not-verified|blocked)|SLOT[12]_APP_STATE=(pin1|puk1)"; then
|
||||||
|
newstate="locked"
|
||||||
|
elif printf "%s\n" "$uim_st" | grep -qE "SLOT[12]_STATE=present" && printf "%s\n" "$uim_st" | grep -q "^PRIMARY_GW_SLOT=0$"; then
|
||||||
|
doas -n /usr/libexec/msm-modem-uim-selection boot >/dev/null 2>&1 || true
|
||||||
|
newstate="$(mmcli -m any -K 2>/dev/null | grep "^modem.generic.state " | cut -d':' -f2 | sed 's/^ //')"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$newstate" ]; then
|
||||||
|
# fake oldstate (boot) and reason (0)
|
||||||
|
sxmo_hook_modem.sh "boot" "$newstate" "0"
|
||||||
|
sxmo_hook_statusbar.sh modem
|
||||||
|
fi
|
||||||
|
) &
|
||||||
|
|
||||||
|
# Monitor for incoming calls
|
||||||
|
dbus-monitor --system "interface='org.freedesktop.ModemManager1.Modem.Voice',type='signal',member='CallAdded'" |
|
||||||
|
while read -r line; do
|
||||||
|
echo "$line" | grep -qE "^signal" && sxmo_modem.sh checkforincomingcalls
|
||||||
|
done &
|
||||||
|
|
||||||
|
# Monitor for incoming texts
|
||||||
|
dbus-monitor --system "interface='org.freedesktop.ModemManager1.Modem.Messaging',type='signal',member='Added'" |
|
||||||
|
while read -r line; do
|
||||||
|
echo "$line" | grep -qE "^signal" && sxmo_modem.sh checkfornewtexts
|
||||||
|
done &
|
||||||
|
|
||||||
|
# Check for new texts periodically
|
||||||
|
sxmo_run_aligned.sh 300 sxmo_modem.sh checkfornewtexts &
|
||||||
|
|
||||||
|
# Monitor for finished calls
|
||||||
|
dbus-monitor --system "interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',arg0='org.freedesktop.ModemManager1.Call'" |
|
||||||
|
while read -r line; do
|
||||||
|
echo "$line" | grep -qE "^signal" && sxmo_modem.sh checkforfinishedcalls
|
||||||
|
done &
|
||||||
|
|
||||||
|
# Periodically remove finished calls
|
||||||
|
sxmo_run_aligned.sh 300 sxmo_modem.sh checkforfinishedcalls &
|
||||||
|
|
||||||
|
# Monitor for modem state change
|
||||||
|
dbus-monitor --system "interface='org.freedesktop.ModemManager1.Modem',type='signal',member='StateChanged'" |
|
||||||
|
while read -r line; do
|
||||||
|
if echo "$line" | grep -qE "^signal.*StateChanged"; then
|
||||||
|
read -r oldstate
|
||||||
|
read -r newstate
|
||||||
|
read -r reason
|
||||||
|
sxmo_hook_modem.sh "$(statenumtoname "$oldstate")" \
|
||||||
|
"$(statenumtoname "$newstate")" \
|
||||||
|
"$(echo "$reason" | sed 's/uint32 //')"
|
||||||
|
sxmo_hook_statusbar.sh modem
|
||||||
|
fi
|
||||||
|
done &
|
||||||
|
|
||||||
|
# Monitor for 3GPP USSD
|
||||||
|
dbus-monitor --system "interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',arg0='org.freedesktop.ModemManager1.Modem.Modem3gpp.Ussd'" |
|
||||||
|
while read -r line; do
|
||||||
|
case "$line" in
|
||||||
|
*"/org/freedesktop/ModemManager1/Modem"*)
|
||||||
|
MODEM=$(echo "$line" | awk -F'[;=]' '{print $6}')
|
||||||
|
CHANGED=0
|
||||||
|
;;
|
||||||
|
*"string \"NetworkNotification"*)
|
||||||
|
TYPE="NetworkNotification"
|
||||||
|
CHANGED=1
|
||||||
|
;;
|
||||||
|
*"string \"NetworkRequest"*)
|
||||||
|
TYPE="NetworkRequest"
|
||||||
|
CHANGED=1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
CHANGED=0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ "$CHANGED" = "1" ]; then
|
||||||
|
# Fetch message (third argument) in sxmo_ussd.sh to save time in this loop
|
||||||
|
sxmo_terminal.sh sxmo_ussd.sh "$MODEM" "$TYPE" "" &
|
||||||
|
fi
|
||||||
|
|
||||||
|
done &
|
||||||
|
|
||||||
|
if [ -f "${SXMO_MMS_BASE_DIR:-"$HOME"/.mms/modemmanager}/mms" ]; then
|
||||||
|
# monitor for received mms
|
||||||
|
dbus-monitor "interface='org.ofono.mms.Service',type='signal',member='MessageAdded'" |
|
||||||
|
while read -r line; do
|
||||||
|
if echo "$line" | grep -q '^object path'; then
|
||||||
|
MESSAGE_PATH="$(echo "$line" | cut -d\" -f2)"
|
||||||
|
fi
|
||||||
|
if echo "$line" | grep -q 'string "received"'; then
|
||||||
|
sxmo_mms.sh processmms "$MESSAGE_PATH"
|
||||||
|
fi
|
||||||
|
done &
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "${SXMO_VVM_BASE_DIR:-"$HOME"/.vvm/modemmanager}/vvm" ]; then
|
||||||
|
# monitor for vvm (Visual Voice Mail)
|
||||||
|
VVM_START=0
|
||||||
|
dbus-monitor "interface='org.kop316.vvm.Service',type='signal',member='MessageAdded'" |
|
||||||
|
while read -r line; do
|
||||||
|
if echo "$line" | grep -q '^object path'; then
|
||||||
|
VVM_ID="$(echo "$line" | cut -d\" -f2 | rev | cut -d'/' -f1 | rev)"
|
||||||
|
VVM_START=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if echo "$line" | grep -q '^]'; then
|
||||||
|
VVM_START=0
|
||||||
|
sxmo_vvm.sh processvvm "$VVM_DATE" "$VVM_SENDER" "$VVM_ID" "$VVM_ATTACHMENT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$VVM_START" -eq 1 ]; then
|
||||||
|
if echo "$line" | grep -q '^string "Date"'; then
|
||||||
|
read -r line
|
||||||
|
VVM_DATE="$(echo "$line" | cut -d\" -f2)"
|
||||||
|
elif echo "$line" | grep -q '^string "Sender"'; then
|
||||||
|
read -r line
|
||||||
|
VVM_SENDER="$(echo "$line" | cut -d\" -f2)"
|
||||||
|
elif echo "$line" | grep -q '^string "Attachments"'; then
|
||||||
|
read -r line
|
||||||
|
VVM_ATTACHMENT="$(echo "$line" | cut -d\" -f2)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done &
|
||||||
|
fi
|
||||||
|
|
||||||
|
wait
|
||||||
|
}
|
||||||
|
|
||||||
|
# new session, clean up all phone related files
|
||||||
|
rm "$XDG_RUNTIME_DIR/sxmo_calls/"* 2>/dev/null || true
|
||||||
|
rm -f "$XDG_RUNTIME_DIR"/sxmo.ring.pid 2>/dev/null
|
||||||
|
rm -f "$SXMO_NOTIFDIR"/incomingcall* 2>/dev/null
|
||||||
|
mainloop
|
||||||
@@ -12,189 +12,209 @@ SXMO_NOTIFDIR="${SXMO_NOTIFDIR:-${XDG_DATA_HOME:-$HOME/.local/share}/sxmo/notifi
|
|||||||
[ -z "$SXMO_NOTIFDIR" ] || [ "$SXMO_NOTIFDIR" = "/" ] && SXMO_NOTIFDIR="$HOME/.local/share/sxmo/notifications"
|
[ -z "$SXMO_NOTIFDIR" ] || [ "$SXMO_NOTIFDIR" = "/" ] && SXMO_NOTIFDIR="$HOME/.local/share/sxmo/notifications"
|
||||||
|
|
||||||
_clear_notif_group() {
|
_clear_notif_group() {
|
||||||
find "$SXMO_NOTIFDIR" -type f | while read -r file; do
|
find "$SXMO_NOTIFDIR" -type f 2>/dev/null | while read -r file; do
|
||||||
if awk NR==1 "$file" | grep -lxq "$1"; then
|
if [ -f "$file" ] && awk NR==1 "$file" 2>/dev/null | grep -lxq "$1"; then
|
||||||
rm "$file"
|
rm -f "$file"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
_handle_new_notif_file(){
|
clear_all() {
|
||||||
file="$1"
|
rm -f "$SXMO_NOTIFDIR"/* 2>/dev/null || true
|
||||||
|
dunstctl close-all >/dev/null 2>&1 || true
|
||||||
|
dunstctl history-clear >/dev/null 2>&1 || true
|
||||||
|
pkill -x dunstify >/dev/null 2>&1 || true
|
||||||
|
sxmo_hook_statusbar.sh notifications >/dev/null 2>&1 || true
|
||||||
|
}
|
||||||
|
|
||||||
if [ "$(wc -l "$file" | cut -d' ' -f1)" -lt 3 ]; then
|
_handle_new_notif_file() {
|
||||||
sxmo_log "Invalid notification file $file found, deleting!"
|
file="$1"
|
||||||
rm -f "$file"
|
[ -f "$file" ] || return 0
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
sxmo_hook_notification.sh "$file" &
|
if [ "$(wc -l < "$file" 2>/dev/null || echo 0)" -lt 3 ]; then
|
||||||
|
sxmo_log "Invalid notification file $file found, deleting!"
|
||||||
|
rm -f "$file"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
group="$(awk NR==1 "$file")"
|
sxmo_hook_notification.sh "$file" &
|
||||||
action="$(awk NR==2 "$file")"
|
|
||||||
msg="$(tail -n+3 "$file" | cut -c1-70)"
|
|
||||||
|
|
||||||
case "$(dunstify --action="default,Open" "$msg")" in
|
group="$(awk NR==1 "$file" 2>/dev/null)"
|
||||||
"2")
|
action="$(awk NR==2 "$file" 2>/dev/null)"
|
||||||
#
|
msg="$(tail -n+3 "$file" 2>/dev/null | cut -c1-70)"
|
||||||
# _clear_notif_group "$group"
|
|
||||||
#
|
(
|
||||||
;;
|
case "$(dunstify --action="default,Open" "$msg" 2>/dev/null)" in
|
||||||
"default")
|
"2")
|
||||||
_clear_notif_group "$group"
|
;;
|
||||||
setsid -f sh -c "$action" > /dev/null 2>&1
|
"default")
|
||||||
;;
|
_clear_notif_group "$group"
|
||||||
esac
|
sxmo_hook_statusbar.sh notifications >/dev/null 2>&1 || true
|
||||||
|
if [ -n "$action" ] && [ "$action" != "none" ]; then
|
||||||
|
setsid -f sh -c "$action" > /dev/null 2>&1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
) &
|
||||||
}
|
}
|
||||||
|
|
||||||
_notifications_hook() {
|
_notifications_hook() {
|
||||||
_cnt=0
|
_cnt=0
|
||||||
for _nf in "$SXMO_NOTIFDIR"/*; do
|
for _nf in "$SXMO_NOTIFDIR"/*; do
|
||||||
[ -f "$_nf" ] && _cnt=$((_cnt + 1))
|
[ -f "$_nf" ] && _cnt=$((_cnt + 1))
|
||||||
done
|
done
|
||||||
sxmo_hook_notifications.sh "$_cnt"
|
sxmo_hook_notifications.sh "$_cnt"
|
||||||
}
|
}
|
||||||
|
|
||||||
monitor() {
|
monitor() {
|
||||||
mkdir -p "$SXMO_NOTIFDIR"
|
mkdir -p "$SXMO_NOTIFDIR"
|
||||||
|
|
||||||
find "$SXMO_NOTIFDIR" -type f | while read -r file; do
|
find "$SXMO_NOTIFDIR" -type f 2>/dev/null | while read -r file; do
|
||||||
_handle_new_notif_file "$file"
|
_handle_new_notif_file "$file"
|
||||||
done
|
done
|
||||||
|
|
||||||
_notifications_hook
|
_notifications_hook
|
||||||
|
|
||||||
fifo="$(mktemp -u)"
|
fifo="$(mktemp -u)"
|
||||||
mkfifo "$fifo"
|
mkfifo "$fifo"
|
||||||
inotifywait -mq -e attrib,move,delete "$SXMO_NOTIFDIR" >> "$fifo" &
|
inotifywait -mq -e close_write,moved_to,delete "$SXMO_NOTIFDIR" >> "$fifo" &
|
||||||
inotif_pid=$!
|
inotif_pid=$!
|
||||||
|
|
||||||
finish() {
|
finish() {
|
||||||
kill "$inotif_pid"
|
kill "$inotif_pid" 2>/dev/null || true
|
||||||
rm "$fifo"
|
rm -f "$fifo"
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
trap 'finish' TERM INT EXIT
|
trap 'finish' TERM INT EXIT
|
||||||
|
|
||||||
while read -r notif_folder notif_type notif_file; do
|
while read -r notif_folder notif_type notif_file; do
|
||||||
if echo "$notif_type" | grep -qE "CREATE|MOVED_TO|ATTRIB"; then
|
if echo "$notif_type" | grep -qE "CLOSE_WRITE|MOVED_TO"; then
|
||||||
_handle_new_notif_file "$notif_folder$notif_file"
|
_handle_new_notif_file "$notif_folder$notif_file"
|
||||||
fi
|
fi
|
||||||
_notifications_hook
|
_notifications_hook
|
||||||
done < "$fifo"
|
done < "$fifo"
|
||||||
|
|
||||||
wait "$inotif_pid"
|
wait "$inotif_pid"
|
||||||
}
|
}
|
||||||
|
|
||||||
_menu_lines() {
|
_menu_lines() {
|
||||||
find "$SXMO_NOTIFDIR" -type f | while read -r file; do
|
find "$SXMO_NOTIFDIR" -type f 2>/dev/null | while read -r file; do
|
||||||
msg="$(tail -n+3 "$file" | tr "\n^" " ")"
|
[ -f "$file" ] || continue
|
||||||
hrandmin="$(stat --printf %y "$file" | grep -oE '[0-9]{2}:[0-9]{2}')"
|
msg="$(tail -n+3 "$file" 2>/dev/null | tr "\n^" " ")"
|
||||||
cat <<EOF
|
hrandmin="$(stat -c %y "$file" 2>/dev/null | grep -oE '[0-9]{2}:[0-9]{2}' | head -n1)"
|
||||||
|
cat <<EOF
|
||||||
$hrandmin $msg^$file
|
$hrandmin $msg^$file
|
||||||
EOF
|
EOF
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
menu() {
|
menu() {
|
||||||
choices="$(cat <<EOF
|
choices="$(cat <<EOF
|
||||||
$icon_cls Close Menu
|
|
||||||
$icon_del Clear Notifications
|
$icon_del Clear Notifications
|
||||||
$(_menu_lines)
|
$(_menu_lines)
|
||||||
|
$icon_cls Close Menu
|
||||||
EOF
|
EOF
|
||||||
)"
|
)"
|
||||||
|
|
||||||
picked="$(
|
picked="$(
|
||||||
printf "%b" "$choices" |
|
printf "%b" "$choices" |
|
||||||
cut -d^ -f1 |
|
cut -d^ -f1 |
|
||||||
sxmo_dmenu.sh -i -p "Notifs"
|
sxmo_dmenu.sh -i -p "Notifs"
|
||||||
)"
|
)"
|
||||||
|
|
||||||
case "$picked" in
|
case "$picked" in
|
||||||
"$icon_cls Close Menu"|"")
|
"$icon_cls Close Menu"|"")
|
||||||
exit
|
exit
|
||||||
;;
|
;;
|
||||||
"$icon_del Clear Notifications")
|
"$icon_del Clear Notifications")
|
||||||
rm "$SXMO_NOTIFDIR"/*
|
clear_all
|
||||||
# we must update statusbar here because this function depends
|
exit
|
||||||
# on number of files in $SXMO_NOTIFDIR
|
;;
|
||||||
sxmo_hook_statusbar.sh notifications
|
*)
|
||||||
exit
|
file="$(
|
||||||
;;
|
printf "%b" "$choices" |
|
||||||
*)
|
grep -F "$picked" |
|
||||||
file="$(
|
cut -d^ -f2 |
|
||||||
printf "%b" "$choices" |
|
head -n1
|
||||||
grep -F "$picked" |
|
)"
|
||||||
cut -d^ -f2
|
if [ -n "$file" ] && [ -f "$file" ]; then
|
||||||
)"
|
group="$(awk NR==1 "$file" 2>/dev/null)"
|
||||||
group="$(awk NR==1 "$file")"
|
action="$(awk NR==2 "$file" 2>/dev/null)"
|
||||||
action="$(awk NR==2 "$file")"
|
_clear_notif_group "$group"
|
||||||
_clear_notif_group "$group"
|
rm -f "$file" 2>/dev/null || true
|
||||||
setsid -f sh -c "$action" > /dev/null 2>&1
|
dunstctl close-all >/dev/null 2>&1 || true
|
||||||
;;
|
sxmo_hook_statusbar.sh notifications >/dev/null 2>&1 || true
|
||||||
esac
|
if [ -n "$action" ] && [ "$action" != "none" ]; then
|
||||||
|
setsid -f sh -c "$action" > /dev/null 2>&1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
new() {
|
new() {
|
||||||
while : ; do
|
while : ; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
-i)
|
-i)
|
||||||
id="$2"
|
id="$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
-g)
|
-g)
|
||||||
group="$2"
|
group="$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
break
|
break
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ "$#" -lt 2 ]; then
|
if [ "$#" -lt 2 ]; then
|
||||||
usage
|
usage
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$id" ]; then
|
if [ -z "$id" ]; then
|
||||||
id="$(tr -dc 'a-zA-Z0-9' < /dev/urandom 2>/dev/null | head -c 10)"
|
id="$(tr -dc 'a-zA-Z0-9' < /dev/urandom 2>/dev/null | head -c 10)"
|
||||||
fi
|
fi
|
||||||
if [ -z "$group" ]; then
|
if [ -z "$group" ]; then
|
||||||
group="$(tr -dc 'a-zA-Z0-9' < /dev/urandom 2>/dev/null | head -c 10)"
|
group="$(tr -dc 'a-zA-Z0-9' < /dev/urandom 2>/dev/null | head -c 10)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
action="$1"
|
action="$1"
|
||||||
msg="$2"
|
msg="$2"
|
||||||
|
|
||||||
touch "$SXMO_NOTIFDIR/$id"
|
mkdir -p "$SXMO_NOTIFDIR"
|
||||||
printf "%s\n%s\n%b\n" "$group" "$action" "$msg" > "$SXMO_NOTIFDIR/$id"
|
printf "%s\n%s\n%b\n" "$group" "$action" "$msg" > "$SXMO_NOTIFDIR/$id"
|
||||||
|
|
||||||
sxmo_hook_statusbar.sh notifications
|
sxmo_hook_statusbar.sh notifications
|
||||||
}
|
}
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
$(basename "$0"): manage sxmo notifications
|
$(basename "$0"): manage sxmo notifications
|
||||||
|
|
||||||
Subcommands:
|
Subcommands:
|
||||||
monitor
|
monitor
|
||||||
Watch for new notification, dispatch libnotify events, handle actions
|
Watch for new notification, dispatch libnotify events, handle actions
|
||||||
menu
|
menu
|
||||||
Open a menu to dismiss notifications
|
Open a menu to dismiss notifications
|
||||||
new [-i id] [-g group] <action> <message...>
|
clear
|
||||||
Register a new notification
|
Clear all notifications and close active Dunst popups
|
||||||
|
new [-i id] [-g group] <action> <message...>
|
||||||
|
Register a new notification
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd="$1"
|
cmd="$1"
|
||||||
shift
|
shift 2>/dev/null || true
|
||||||
case "$cmd" in
|
case "$cmd" in
|
||||||
monitor) monitor "$@";;
|
monitor) monitor "$@" ;;
|
||||||
menu) menu "$@";;
|
menu) menu "$@" ;;
|
||||||
new) new "$@";;
|
clear) clear_all ;;
|
||||||
*)
|
new) new "$@" ;;
|
||||||
usage
|
*)
|
||||||
exit 1
|
usage
|
||||||
;;
|
exit 1
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -8,7 +8,7 @@ if [ -r "$CONF_FILE" ]; then
|
|||||||
. "$CONF_FILE"
|
. "$CONF_FILE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
SIM_WAIT_TIME="${SIM_WAIT_TIME:-${sim_wait_time:-4}}"
|
SIM_WAIT_TIME="${SIM_WAIT_TIME:-${sim_wait_time:-10}}"
|
||||||
PREFERRED_SIM_SLOT="${PREFERRED_SIM_SLOT:-${preferred_sim_slot:-1}}"
|
PREFERRED_SIM_SLOT="${PREFERRED_SIM_SLOT:-${preferred_sim_slot:-1}}"
|
||||||
QMICLI_MODEM=""
|
QMICLI_MODEM=""
|
||||||
|
|
||||||
@@ -16,15 +16,25 @@ detect_qmicli_modem() {
|
|||||||
if ! command -v qmicli >/dev/null 2>&1; then
|
if ! command -v qmicli >/dev/null 2>&1; then
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
if [ -e "/dev/modem" ]; then
|
if qmicli --silent -pd qrtr://0 --uim-noop >/dev/null 2>&1; then
|
||||||
QMICLI_MODEM="qmicli --silent -d /dev/modem"
|
|
||||||
return 0
|
|
||||||
elif [ -e "/dev/wwan0qmi0" ]; then
|
|
||||||
QMICLI_MODEM="qmicli --silent -d /dev/wwan0qmi0 --device-open-qmi"
|
|
||||||
return 0
|
|
||||||
elif qmicli --silent -pd qrtr://0 --uim-noop >/dev/null 2>&1; then
|
|
||||||
QMICLI_MODEM="qmicli --silent -pd qrtr://0"
|
QMICLI_MODEM="qmicli --silent -pd qrtr://0"
|
||||||
return 0
|
return 0
|
||||||
|
elif [ -e "/dev/wwan0qmi0" ]; then
|
||||||
|
if qmicli --silent -pd /dev/wwan0qmi0 --device-open-qmi --uim-noop >/dev/null 2>&1; then
|
||||||
|
QMICLI_MODEM="qmicli --silent -pd /dev/wwan0qmi0 --device-open-qmi"
|
||||||
|
return 0
|
||||||
|
elif qmicli --silent -d /dev/wwan0qmi0 --device-open-qmi --uim-noop >/dev/null 2>&1; then
|
||||||
|
QMICLI_MODEM="qmicli --silent -d /dev/wwan0qmi0 --device-open-qmi"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
elif [ -e "/dev/modem" ]; then
|
||||||
|
if qmicli --silent -pd /dev/modem --uim-noop >/dev/null 2>&1; then
|
||||||
|
QMICLI_MODEM="qmicli --silent -pd /dev/modem"
|
||||||
|
return 0
|
||||||
|
elif qmicli --silent -d /dev/modem --uim-noop >/dev/null 2>&1; then
|
||||||
|
QMICLI_MODEM="qmicli --silent -d /dev/modem"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
@@ -64,6 +74,8 @@ parse_uim_card_status() {
|
|||||||
pin1_state[s] = "not-initialized"
|
pin1_state[s] = "not-initialized"
|
||||||
pin1_ret[s] = 0
|
pin1_ret[s] = 0
|
||||||
puk1_ret[s] = 0
|
puk1_ret[s] = 0
|
||||||
|
want_aid[s] = 0
|
||||||
|
need_aid_line[s] = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/Primary GW:/ {
|
/Primary GW:/ {
|
||||||
@@ -95,7 +107,7 @@ parse_uim_card_status() {
|
|||||||
}
|
}
|
||||||
if (!in_app && $0 ~ /Card state:/) {
|
if (!in_app && $0 ~ /Card state:/) {
|
||||||
line = $0
|
line = $0
|
||||||
sub(/.*Card state: \x27/, "", line)
|
sub(/.*Card state:[[:space:]]*\x27/, "", line)
|
||||||
sub(/\x27.*/, "", line)
|
sub(/\x27.*/, "", line)
|
||||||
rawstate[cur_slot] = line
|
rawstate[cur_slot] = line
|
||||||
if (line == "present") cstate[cur_slot] = "present"
|
if (line == "present") cstate[cur_slot] = "present"
|
||||||
@@ -104,25 +116,25 @@ parse_uim_card_status() {
|
|||||||
}
|
}
|
||||||
if (!in_app && $0 ~ /UPIN state:/) {
|
if (!in_app && $0 ~ /UPIN state:/) {
|
||||||
line = $0
|
line = $0
|
||||||
sub(/.*UPIN state: \x27/, "", line)
|
sub(/.*UPIN state:[[:space:]]*\x27/, "", line)
|
||||||
sub(/\x27.*/, "", line)
|
sub(/\x27.*/, "", line)
|
||||||
upin_state[cur_slot] = line
|
upin_state[cur_slot] = line
|
||||||
}
|
}
|
||||||
if (!in_app && $0 ~ /UPIN retries:/) {
|
if (!in_app && $0 ~ /UPIN retries:/) {
|
||||||
line = $0
|
line = $0
|
||||||
sub(/.*UPIN retries: \x27/, "", line)
|
sub(/.*UPIN retries:[[:space:]]*\x27/, "", line)
|
||||||
sub(/\x27.*/, "", line)
|
sub(/\x27.*/, "", line)
|
||||||
upin_ret[cur_slot] = line + 0
|
upin_ret[cur_slot] = line + 0
|
||||||
}
|
}
|
||||||
if (!in_app && $0 ~ /UPUK retries:/) {
|
if (!in_app && $0 ~ /UPUK retries:/) {
|
||||||
line = $0
|
line = $0
|
||||||
sub(/.*UPUK retries: \x27/, "", line)
|
sub(/.*UPUK retries:[[:space:]]*\x27/, "", line)
|
||||||
sub(/\x27.*/, "", line)
|
sub(/\x27.*/, "", line)
|
||||||
upuk_ret[cur_slot] = line + 0
|
upuk_ret[cur_slot] = line + 0
|
||||||
}
|
}
|
||||||
if (in_app && $0 ~ /Application type:/) {
|
if (in_app && $0 ~ /Application type:/) {
|
||||||
line = $0
|
line = $0
|
||||||
sub(/.*Application type: \x27/, "", line)
|
sub(/.*Application type:[[:space:]]*\x27/, "", line)
|
||||||
sub(/\x27.*/, "", line)
|
sub(/\x27.*/, "", line)
|
||||||
if (line ~ /^usim/) {
|
if (line ~ /^usim/) {
|
||||||
app_type[cur_slot] = "usim"
|
app_type[cur_slot] = "usim"
|
||||||
@@ -130,13 +142,16 @@ parse_uim_card_status() {
|
|||||||
} else if (line ~ /^sim/ && app_type[cur_slot] != "usim") {
|
} else if (line ~ /^sim/ && app_type[cur_slot] != "usim") {
|
||||||
app_type[cur_slot] = "sim"
|
app_type[cur_slot] = "sim"
|
||||||
want_aid[cur_slot] = 1
|
want_aid[cur_slot] = 1
|
||||||
|
} else if (app_type[cur_slot] == "none") {
|
||||||
|
app_type[cur_slot] = "sim"
|
||||||
|
want_aid[cur_slot] = 1
|
||||||
} else {
|
} else {
|
||||||
want_aid[cur_slot] = 0
|
want_aid[cur_slot] = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (in_app && $0 ~ /Application state:/ && want_aid[cur_slot] > 0) {
|
if (in_app && $0 ~ /Application state:/ && want_aid[cur_slot] > 0) {
|
||||||
line = $0
|
line = $0
|
||||||
sub(/.*Application state: \x27/, "", line)
|
sub(/.*Application state:[[:space:]]*\x27/, "", line)
|
||||||
sub(/\x27.*/, "", line)
|
sub(/\x27.*/, "", line)
|
||||||
app_state[cur_slot] = line
|
app_state[cur_slot] = line
|
||||||
}
|
}
|
||||||
@@ -147,26 +162,26 @@ parse_uim_card_status() {
|
|||||||
if (in_app && need_aid_line[cur_slot] == 1) {
|
if (in_app && need_aid_line[cur_slot] == 1) {
|
||||||
line = $0
|
line = $0
|
||||||
gsub(/^[[:space:]]+|[[:space:]]+$/, "", line)
|
gsub(/^[[:space:]]+|[[:space:]]+$/, "", line)
|
||||||
if (line != "") {
|
if (line != "" && line !~ /:.*\x27/) {
|
||||||
aid[cur_slot] = line
|
aid[cur_slot] = line
|
||||||
}
|
}
|
||||||
need_aid_line[cur_slot] = 0
|
need_aid_line[cur_slot] = 0
|
||||||
}
|
}
|
||||||
if (in_app && $0 ~ /PIN1 state:/ && want_aid[cur_slot] > 0) {
|
if (in_app && $0 ~ /PIN1 state:/ && want_aid[cur_slot] > 0) {
|
||||||
line = $0
|
line = $0
|
||||||
sub(/.*PIN1 state: \x27/, "", line)
|
sub(/.*PIN1 state:[[:space:]]*\x27/, "", line)
|
||||||
sub(/\x27.*/, "", line)
|
sub(/\x27.*/, "", line)
|
||||||
pin1_state[cur_slot] = line
|
pin1_state[cur_slot] = line
|
||||||
}
|
}
|
||||||
if (in_app && $0 ~ /PIN1 retries:/ && want_aid[cur_slot] > 0) {
|
if (in_app && $0 ~ /PIN1 retries:/ && want_aid[cur_slot] > 0) {
|
||||||
line = $0
|
line = $0
|
||||||
sub(/.*PIN1 retries: \x27/, "", line)
|
sub(/.*PIN1 retries:[[:space:]]*\x27/, "", line)
|
||||||
sub(/\x27.*/, "", line)
|
sub(/\x27.*/, "", line)
|
||||||
pin1_ret[cur_slot] = line + 0
|
pin1_ret[cur_slot] = line + 0
|
||||||
}
|
}
|
||||||
if (in_app && $0 ~ /PUK1 retries:/ && want_aid[cur_slot] > 0) {
|
if (in_app && $0 ~ /PUK1 retries:/ && want_aid[cur_slot] > 0) {
|
||||||
line = $0
|
line = $0
|
||||||
sub(/.*PUK1 retries: \x27/, "", line)
|
sub(/.*PUK1 retries:[[:space:]]*\x27/, "", line)
|
||||||
sub(/\x27.*/, "", line)
|
sub(/\x27.*/, "", line)
|
||||||
puk1_ret[cur_slot] = line + 0
|
puk1_ret[cur_slot] = line + 0
|
||||||
}
|
}
|
||||||
@@ -192,8 +207,116 @@ parse_uim_card_status() {
|
|||||||
'
|
'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parse_nas_serving_system() {
|
||||||
|
raw_nas="$1"
|
||||||
|
printf "%s\n" "$raw_nas" | awk '
|
||||||
|
BEGIN {
|
||||||
|
reg_state = "unknown"
|
||||||
|
cs_state = "unknown"
|
||||||
|
ps_state = "unknown"
|
||||||
|
rat = ""
|
||||||
|
mcc = ""
|
||||||
|
mnc = ""
|
||||||
|
op_desc = ""
|
||||||
|
roam = "off"
|
||||||
|
in_rat = 0
|
||||||
|
in_plmn = 0
|
||||||
|
in_roam = 0
|
||||||
|
}
|
||||||
|
/^[[:space:]]*Registration state:/ {
|
||||||
|
line = $0
|
||||||
|
sub(/.*Registration state:[[:space:]]*\x27/, "", line)
|
||||||
|
sub(/\x27.*/, "", line)
|
||||||
|
reg_state = line
|
||||||
|
in_rat = 0; in_plmn = 0; in_roam = 0
|
||||||
|
next
|
||||||
|
}
|
||||||
|
/^[[:space:]]*CS:/ {
|
||||||
|
line = $0
|
||||||
|
sub(/.*CS:[[:space:]]*\x27/, "", line)
|
||||||
|
sub(/\x27.*/, "", line)
|
||||||
|
cs_state = line
|
||||||
|
next
|
||||||
|
}
|
||||||
|
/^[[:space:]]*PS:/ {
|
||||||
|
line = $0
|
||||||
|
sub(/.*PS:[[:space:]]*\x27/, "", line)
|
||||||
|
sub(/\x27.*/, "", line)
|
||||||
|
ps_state = line
|
||||||
|
next
|
||||||
|
}
|
||||||
|
/^[[:space:]]*Radio interfaces:/ {
|
||||||
|
in_rat = 1; in_plmn = 0; in_roam = 0
|
||||||
|
next
|
||||||
|
}
|
||||||
|
/^[[:space:]]*Data service capabilities:/ {
|
||||||
|
in_rat = 0
|
||||||
|
next
|
||||||
|
}
|
||||||
|
/^[[:space:]]*Current PLMN:/ {
|
||||||
|
in_plmn = 1; in_rat = 0; in_roam = 0
|
||||||
|
next
|
||||||
|
}
|
||||||
|
/^[[:space:]]*Roaming indicators:/ {
|
||||||
|
in_roam = 1; in_plmn = 0; in_rat = 0
|
||||||
|
next
|
||||||
|
}
|
||||||
|
/^[[:space:]]*Default roaming status:/ {
|
||||||
|
line = $0
|
||||||
|
sub(/.*Default roaming status:[[:space:]]*\x27/, "", line)
|
||||||
|
sub(/\x27.*/, "", line)
|
||||||
|
roam = line
|
||||||
|
in_roam = 0
|
||||||
|
next
|
||||||
|
}
|
||||||
|
in_rat && /^[[:space:]]*\[[0-9]+\]:/ {
|
||||||
|
line = $0
|
||||||
|
sub(/.*\[[0-9]+\]:[[:space:]]*\x27/, "", line)
|
||||||
|
sub(/\x27.*/, "", line)
|
||||||
|
if (line != "" && line != "none" && rat == "") rat = line
|
||||||
|
}
|
||||||
|
in_plmn && /MCC:/ {
|
||||||
|
line = $0
|
||||||
|
sub(/.*MCC:[[:space:]]*\x27/, "", line)
|
||||||
|
sub(/\x27.*/, "", line)
|
||||||
|
mcc = line
|
||||||
|
}
|
||||||
|
in_plmn && /MNC:/ {
|
||||||
|
line = $0
|
||||||
|
sub(/.*MNC:[[:space:]]*\x27/, "", line)
|
||||||
|
sub(/\x27.*/, "", line)
|
||||||
|
mnc = line
|
||||||
|
}
|
||||||
|
in_plmn && /Description:/ {
|
||||||
|
line = $0
|
||||||
|
sub(/.*Description:[[:space:]]*\x27/, "", line)
|
||||||
|
sub(/\x27.*/, "", line)
|
||||||
|
gsub(/[\r\n\t]/, " ", line)
|
||||||
|
op_desc = line
|
||||||
|
in_plmn = 0
|
||||||
|
}
|
||||||
|
in_roam && /^[[:space:]]*\[[0-9]+\]:/ {
|
||||||
|
line = $0
|
||||||
|
sub(/.*\[[0-9]+\]:[[:space:]]*\x27/, "", line)
|
||||||
|
sub(/\x27.*/, "", line)
|
||||||
|
if (line == "on") roam = "on"
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
printf "NAS_REG_STATE=%s\n", reg_state
|
||||||
|
printf "NAS_CS_STATE=%s\n", cs_state
|
||||||
|
printf "NAS_PS_STATE=%s\n", ps_state
|
||||||
|
printf "NAS_RAT=%s\n", rat
|
||||||
|
printf "NAS_MCC=%s\n", mcc
|
||||||
|
printf "NAS_MNC=%s\n", mnc
|
||||||
|
printf "NAS_OPERATOR=%s\n", op_desc
|
||||||
|
printf "NAS_ROAMING=%s\n", roam
|
||||||
|
}
|
||||||
|
'
|
||||||
|
}
|
||||||
|
|
||||||
save_preferred_slot() {
|
save_preferred_slot() {
|
||||||
target_slot="$1"
|
target_slot="$1"
|
||||||
|
PREFERRED_SIM_SLOT="$target_slot"
|
||||||
if [ -f "$CONF_FILE" ]; then
|
if [ -f "$CONF_FILE" ]; then
|
||||||
if grep -q "^preferred_sim_slot=" "$CONF_FILE"; then
|
if grep -q "^preferred_sim_slot=" "$CONF_FILE"; then
|
||||||
sed -i "s/^preferred_sim_slot=.*/preferred_sim_slot=$target_slot/" "$CONF_FILE"
|
sed -i "s/^preferred_sim_slot=.*/preferred_sim_slot=$target_slot/" "$CONF_FILE"
|
||||||
@@ -201,7 +324,7 @@ save_preferred_slot() {
|
|||||||
printf "\npreferred_sim_slot=%s\n" "$target_slot" >> "$CONF_FILE"
|
printf "\npreferred_sim_slot=%s\n" "$target_slot" >> "$CONF_FILE"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
printf "sim_wait_time=4\npreferred_sim_slot=%s\n" "$target_slot" > "$CONF_FILE"
|
printf "sim_wait_time=10\npreferred_sim_slot=%s\n" "$target_slot" > "$CONF_FILE"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,52 +337,154 @@ provision_slot() {
|
|||||||
return 2
|
return 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
$QMICLI_MODEM --dms-set-operating-mode=online >/dev/null 2>&1 || true
|
||||||
|
|
||||||
QMI_CARDS="$($QMICLI_MODEM --uim-get-card-status 2>/dev/null || true)"
|
QMI_CARDS="$($QMICLI_MODEM --uim-get-card-status 2>/dev/null || true)"
|
||||||
count=0
|
count=0
|
||||||
while ! printf "%s" "$QMI_CARDS" | grep -Fq "Card state: 'present'"; do
|
while : ; do
|
||||||
|
if [ -n "$QMI_CARDS" ]; then
|
||||||
|
eval "$(parse_uim_card_status "$QMI_CARDS" "$req_slot")"
|
||||||
|
if [ "$req_slot" = "2" ] && [ "$SLOT2_STATE" = "present" ] && [ "$SLOT2_APP_TYPE" != "none" ]; then
|
||||||
|
break
|
||||||
|
elif [ "$req_slot" != "2" ] && [ "$SLOT1_STATE" = "present" ] && [ "$SLOT1_APP_TYPE" != "none" ]; then
|
||||||
|
break
|
||||||
|
elif [ "$count" -ge 3 ] && { { [ "$SLOT1_STATE" = "present" ] && [ "$SLOT1_APP_TYPE" != "none" ]; } || { [ "$SLOT2_STATE" = "present" ] && [ "$SLOT2_APP_TYPE" != "none" ]; }; }; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
fi
|
||||||
if [ "$count" -ge "$SIM_WAIT_TIME" ]; then
|
if [ "$count" -ge "$SIM_WAIT_TIME" ]; then
|
||||||
echo "No SIM detected after $SIM_WAIT_TIME seconds."
|
break
|
||||||
return 0
|
|
||||||
fi
|
fi
|
||||||
sleep 1
|
sleep 1
|
||||||
count=$((count + 1))
|
count=$((count + 1))
|
||||||
QMI_CARDS="$($QMICLI_MODEM --uim-get-card-status 2>/dev/null || true)"
|
QMI_CARDS="$($QMICLI_MODEM --uim-get-card-status 2>/dev/null || true)"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
if [ -z "$QMI_CARDS" ]; then
|
||||||
|
echo "No SIM card status returned."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
eval "$(parse_uim_card_status "$QMI_CARDS" "$req_slot")"
|
eval "$(parse_uim_card_status "$QMI_CARDS" "$req_slot")"
|
||||||
|
|
||||||
chosen_slot=""
|
chosen_slot=""
|
||||||
chosen_aid=""
|
chosen_aid=""
|
||||||
if [ "$req_slot" = "2" ]; then
|
if [ "$req_slot" = "2" ]; then
|
||||||
if [ "$SLOT2_STATE" = "present" ] && [ -n "$SLOT2_AID" ]; then
|
if [ "$SLOT2_STATE" = "present" ]; then
|
||||||
chosen_slot="2"
|
chosen_slot="2"
|
||||||
chosen_aid="$SLOT2_AID"
|
chosen_aid="$SLOT2_AID"
|
||||||
elif [ "$SLOT1_STATE" = "present" ] && [ -n "$SLOT1_AID" ]; then
|
elif [ "$SLOT1_STATE" = "present" ]; then
|
||||||
chosen_slot="1"
|
chosen_slot="1"
|
||||||
chosen_aid="$SLOT1_AID"
|
chosen_aid="$SLOT1_AID"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if [ "$SLOT1_STATE" = "present" ] && [ -n "$SLOT1_AID" ]; then
|
if [ "$SLOT1_STATE" = "present" ]; then
|
||||||
chosen_slot="1"
|
chosen_slot="1"
|
||||||
chosen_aid="$SLOT1_AID"
|
chosen_aid="$SLOT1_AID"
|
||||||
elif [ "$SLOT2_STATE" = "present" ] && [ -n "$SLOT2_AID" ]; then
|
elif [ "$SLOT2_STATE" = "present" ]; then
|
||||||
chosen_slot="2"
|
chosen_slot="2"
|
||||||
chosen_aid="$SLOT2_AID"
|
chosen_aid="$SLOT2_AID"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$chosen_slot" ] || [ -z "$chosen_aid" ]; then
|
if [ -z "$chosen_slot" ]; then
|
||||||
echo "No valid USIM/SIM application found on any slot."
|
echo "No SIM detected after $SIM_WAIT_TIME seconds."
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$PRIMARY_GW_SLOT" != "0" ]; then
|
if [ "$chosen_slot" != "$PREFERRED_SIM_SLOT" ]; then
|
||||||
|
save_preferred_slot "$chosen_slot"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If already provisioned on the chosen slot and application is ready, keep session intact
|
||||||
|
eval "chosen_app_state=\$SLOT${chosen_slot}_APP_STATE"
|
||||||
|
if [ "$PRIMARY_GW_SLOT" = "$chosen_slot" ] && [ "$chosen_app_state" = "ready" ]; then
|
||||||
|
echo "Slot $chosen_slot already active and ready."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$PRIMARY_GW_SLOT" != "0" ] && [ "$PRIMARY_GW_SLOT" != "$chosen_slot" ]; then
|
||||||
$QMICLI_MODEM --uim-change-provisioning-session='activate=no,session-type=primary-gw-provisioning' >/dev/null 2>&1 || true
|
$QMICLI_MODEM --uim-change-provisioning-session='activate=no,session-type=primary-gw-provisioning' >/dev/null 2>&1 || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Selecting AID $chosen_aid on slot $chosen_slot"
|
if [ -n "$chosen_aid" ]; then
|
||||||
$QMICLI_MODEM --uim-change-provisioning-session="slot=$chosen_slot,activate=yes,session-type=primary-gw-provisioning,aid=$chosen_aid" >/dev/null
|
echo "Selecting AID $chosen_aid on slot $chosen_slot"
|
||||||
return $?
|
if ! $QMICLI_MODEM --uim-change-provisioning-session="slot=$chosen_slot,activate=yes,session-type=primary-gw-provisioning,aid=$chosen_aid" >/dev/null 2>&1; then
|
||||||
|
$QMICLI_MODEM --uim-change-provisioning-session="slot=$chosen_slot,activate=yes,session-type=primary-gw-provisioning" >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Selecting slot $chosen_slot"
|
||||||
|
$QMICLI_MODEM --uim-change-provisioning-session="slot=$chosen_slot,activate=yes,session-type=primary-gw-provisioning" >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
enable_and_register_modem() {
|
||||||
|
target_slot="${1:-$PREFERRED_SIM_SLOT}"
|
||||||
|
if detect_qmicli_modem; then
|
||||||
|
$QMICLI_MODEM --dms-set-operating-mode=online >/dev/null 2>&1 || true
|
||||||
|
$QMICLI_MODEM --nas-initiate-network-register >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
i=0
|
||||||
|
mm_state=""
|
||||||
|
while [ "$i" -lt 12 ]; do
|
||||||
|
mm_state="$(mmcli -m any -K 2>/dev/null | awk -F': ' '/^modem\.generic\.state / {print $2; exit}' || true)"
|
||||||
|
if [ -n "$mm_state" ]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
i=$((i + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$mm_state" = "failed" ]; then
|
||||||
|
if command -v rc-service >/dev/null 2>&1; then
|
||||||
|
rc-service modemmanager restart >/dev/null 2>&1 || true
|
||||||
|
elif command -v systemctl >/dev/null 2>&1; then
|
||||||
|
systemctl restart ModemManager >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
i=0
|
||||||
|
mm_state=""
|
||||||
|
while [ "$i" -lt 12 ]; do
|
||||||
|
mm_state="$(mmcli -m any -K 2>/dev/null | awk -F': ' '/^modem\.generic\.state / {print $2; exit}' || true)"
|
||||||
|
if [ -n "$mm_state" ] && [ "$mm_state" != "failed" ]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
i=$((i + 1))
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$mm_state" ] || [ "$mm_state" = "locked" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
i=0
|
||||||
|
while [ "$i" -lt 10 ]; do
|
||||||
|
mm_state="$(mmcli -m any -K 2>/dev/null | awk -F': ' '/^modem\.generic\.state / {print $2; exit}' || true)"
|
||||||
|
case "$mm_state" in
|
||||||
|
disabled)
|
||||||
|
mmcli -m any -e >/dev/null 2>&1 || true
|
||||||
|
;;
|
||||||
|
enabled)
|
||||||
|
mmcli -m any --3gpp-register-home >/dev/null 2>&1 || true
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
searching|registered|connected|connecting)
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
locked)
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
sleep 1
|
||||||
|
i=$((i + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
mmcli -m any --3gpp-register-home >/dev/null 2>&1 || true
|
||||||
|
if command -v sxmo_hook_statusbar.sh >/dev/null 2>&1; then
|
||||||
|
DISPLAY="${DISPLAY:-:0}" sxmo_hook_statusbar.sh modem >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd="${1:-boot}"
|
cmd="${1:-boot}"
|
||||||
@@ -276,7 +501,8 @@ case "$cmd" in
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
provision_slot "$PREFERRED_SIM_SLOT" 45
|
provision_slot "$PREFERRED_SIM_SLOT" 45
|
||||||
exit $?
|
( enable_and_register_modem "$PREFERRED_SIM_SLOT" ) >/dev/null 2>&1 </dev/null &
|
||||||
|
exit 0
|
||||||
;;
|
;;
|
||||||
|
|
||||||
status)
|
status)
|
||||||
@@ -293,6 +519,10 @@ case "$cmd" in
|
|||||||
fi
|
fi
|
||||||
echo "MODEM_AVAILABLE=1"
|
echo "MODEM_AVAILABLE=1"
|
||||||
parse_uim_card_status "$QMI_CARDS" "$PREFERRED_SIM_SLOT"
|
parse_uim_card_status "$QMI_CARDS" "$PREFERRED_SIM_SLOT"
|
||||||
|
QMI_NAS="$($QMICLI_MODEM --nas-get-serving-system 2>/dev/null || true)"
|
||||||
|
if [ -n "$QMI_NAS" ]; then
|
||||||
|
parse_nas_serving_system "$QMI_NAS"
|
||||||
|
fi
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
|
|
||||||
@@ -303,13 +533,14 @@ case "$cmd" in
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
save_preferred_slot "$target"
|
save_preferred_slot "$target"
|
||||||
SIM_WAIT_TIME=2
|
SIM_WAIT_TIME=3
|
||||||
provision_slot "$target" 5
|
provision_slot "$target" 5
|
||||||
if command -v rc-service >/dev/null 2>&1; then
|
if command -v rc-service >/dev/null 2>&1; then
|
||||||
rc-service modemmanager restart >/dev/null 2>&1 || true
|
rc-service modemmanager restart >/dev/null 2>&1 || true
|
||||||
elif command -v systemctl >/dev/null 2>&1; then
|
elif command -v systemctl >/dev/null 2>&1; then
|
||||||
systemctl restart ModemManager >/dev/null 2>&1 || true
|
systemctl restart ModemManager >/dev/null 2>&1 || true
|
||||||
fi
|
fi
|
||||||
|
( enable_and_register_modem "$target" ) >/dev/null 2>&1 </dev/null &
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
|
|
||||||
@@ -320,18 +551,27 @@ case "$cmd" in
|
|||||||
echo "Missing PIN" >&2
|
echo "Missing PIN" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
sim_id="$(mmcli -m any 2>/dev/null | grep -oE 'SIM/[0-9]+' | head -n1 | cut -d'/' -f2 || true)"
|
verified=0
|
||||||
if [ -n "$sim_id" ] && mmcli -i "$sim_id" --pin="$pin" >/dev/null 2>&1; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
if detect_qmicli_modem; then
|
if detect_qmicli_modem; then
|
||||||
if $QMICLI_MODEM --uim-verify-pin="PIN1,$pin,session-type=primary-gw-provisioning" >/dev/null 2>&1; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
if $QMICLI_MODEM --uim-verify-pin="PIN1,$pin,session-type=card-slot-$slot" >/dev/null 2>&1; then
|
if $QMICLI_MODEM --uim-verify-pin="PIN1,$pin,session-type=card-slot-$slot" >/dev/null 2>&1; then
|
||||||
exit 0
|
verified=1
|
||||||
|
elif $QMICLI_MODEM --uim-verify-pin="PIN1,$pin,session-type=primary-gw-provisioning" >/dev/null 2>&1; then
|
||||||
|
verified=1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
if [ "$verified" = "0" ]; then
|
||||||
|
sim_id="$(mmcli -m any 2>/dev/null | grep -oE 'SIM/[0-9]+' | head -n1 | cut -d'/' -f2 || true)"
|
||||||
|
if [ -n "$sim_id" ] && mmcli -i "$sim_id" --pin="$pin" >/dev/null 2>&1; then
|
||||||
|
verified=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ "$verified" = "1" ]; then
|
||||||
|
save_preferred_slot "$slot"
|
||||||
|
SIM_WAIT_TIME=2
|
||||||
|
provision_slot "$slot" 3 >/dev/null 2>&1 || true
|
||||||
|
( enable_and_register_modem "$slot" ) >/dev/null 2>&1 </dev/null &
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
|
|
||||||
@@ -343,18 +583,27 @@ case "$cmd" in
|
|||||||
echo "Missing PUK or new PIN" >&2
|
echo "Missing PUK or new PIN" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
sim_id="$(mmcli -m any 2>/dev/null | grep -oE 'SIM/[0-9]+' | head -n1 | cut -d'/' -f2 || true)"
|
unblocked=0
|
||||||
if [ -n "$sim_id" ] && mmcli -i "$sim_id" --puk="$puk" --pin="$newpin" >/dev/null 2>&1; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
if detect_qmicli_modem; then
|
if detect_qmicli_modem; then
|
||||||
if $QMICLI_MODEM --uim-unblock-pin="PIN1,$puk,$newpin,session-type=primary-gw-provisioning" >/dev/null 2>&1; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
if $QMICLI_MODEM --uim-unblock-pin="PIN1,$puk,$newpin,session-type=card-slot-$slot" >/dev/null 2>&1; then
|
if $QMICLI_MODEM --uim-unblock-pin="PIN1,$puk,$newpin,session-type=card-slot-$slot" >/dev/null 2>&1; then
|
||||||
exit 0
|
unblocked=1
|
||||||
|
elif $QMICLI_MODEM --uim-unblock-pin="PIN1,$puk,$newpin,session-type=primary-gw-provisioning" >/dev/null 2>&1; then
|
||||||
|
unblocked=1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
if [ "$unblocked" = "0" ]; then
|
||||||
|
sim_id="$(mmcli -m any 2>/dev/null | grep -oE 'SIM/[0-9]+' | head -n1 | cut -d'/' -f2 || true)"
|
||||||
|
if [ -n "$sim_id" ] && mmcli -i "$sim_id" --puk="$puk" --pin="$newpin" >/dev/null 2>&1; then
|
||||||
|
unblocked=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ "$unblocked" = "1" ]; then
|
||||||
|
save_preferred_slot "$slot"
|
||||||
|
SIM_WAIT_TIME=2
|
||||||
|
provision_slot "$slot" 3 >/dev/null 2>&1 || true
|
||||||
|
( enable_and_register_modem "$slot" ) >/dev/null 2>&1 </dev/null &
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
|
|
||||||
@@ -366,6 +615,14 @@ case "$cmd" in
|
|||||||
echo "Usage: $0 set-pin-lock <1|2> <enable|disable> <pin>" >&2
|
echo "Usage: $0 set-pin-lock <1|2> <enable|disable> <pin>" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
if detect_qmicli_modem; then
|
||||||
|
if $QMICLI_MODEM --uim-set-pin-protection="PIN1,$mode,$pin,session-type=card-slot-$slot" >/dev/null 2>&1; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
if $QMICLI_MODEM --uim-set-pin-protection="PIN1,$mode,$pin,session-type=primary-gw-provisioning" >/dev/null 2>&1; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
sim_id="$(mmcli -m any 2>/dev/null | grep -oE 'SIM/[0-9]+' | head -n1 | cut -d'/' -f2 || true)"
|
sim_id="$(mmcli -m any 2>/dev/null | grep -oE 'SIM/[0-9]+' | head -n1 | cut -d'/' -f2 || true)"
|
||||||
if [ -n "$sim_id" ]; then
|
if [ -n "$sim_id" ]; then
|
||||||
if [ "$mode" = "enable" ] && mmcli -i "$sim_id" --enable-pin --pin="$pin" >/dev/null 2>&1; then
|
if [ "$mode" = "enable" ] && mmcli -i "$sim_id" --enable-pin --pin="$pin" >/dev/null 2>&1; then
|
||||||
@@ -374,14 +631,6 @@ case "$cmd" in
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
if detect_qmicli_modem; then
|
|
||||||
if $QMICLI_MODEM --uim-set-pin-protection="PIN1,$mode,$pin,session-type=primary-gw-provisioning" >/dev/null 2>&1; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
if $QMICLI_MODEM --uim-set-pin-protection="PIN1,$mode,$pin,session-type=card-slot-$slot" >/dev/null 2>&1; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
|
|
||||||
@@ -393,17 +642,17 @@ case "$cmd" in
|
|||||||
echo "Usage: $0 change-pin <1|2> <oldpin> <newpin>" >&2
|
echo "Usage: $0 change-pin <1|2> <oldpin> <newpin>" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
sim_id="$(mmcli -m any 2>/dev/null | grep -oE 'SIM/[0-9]+' | head -n1 | cut -d'/' -f2 || true)"
|
|
||||||
if [ -n "$sim_id" ] && mmcli -i "$sim_id" --change-pin="$newpin" --pin="$oldpin" >/dev/null 2>&1; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
if detect_qmicli_modem; then
|
if detect_qmicli_modem; then
|
||||||
if $QMICLI_MODEM --uim-change-pin="PIN1,$oldpin,$newpin,session-type=primary-gw-provisioning" >/dev/null 2>&1; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
if $QMICLI_MODEM --uim-change-pin="PIN1,$oldpin,$newpin,session-type=card-slot-$slot" >/dev/null 2>&1; then
|
if $QMICLI_MODEM --uim-change-pin="PIN1,$oldpin,$newpin,session-type=card-slot-$slot" >/dev/null 2>&1; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
if $QMICLI_MODEM --uim-change-pin="PIN1,$oldpin,$newpin,session-type=primary-gw-provisioning" >/dev/null 2>&1; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
sim_id="$(mmcli -m any 2>/dev/null | grep -oE 'SIM/[0-9]+' | head -n1 | cut -d'/' -f2 || true)"
|
||||||
|
if [ -n "$sim_id" ] && mmcli -i "$sim_id" --change-pin="$newpin" --pin="$oldpin" >/dev/null 2>&1; then
|
||||||
|
exit 0
|
||||||
fi
|
fi
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
@@ -505,7 +754,12 @@ case "$cmd" in
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
resp=""
|
resp=""
|
||||||
for candidate in "$port" /dev/wwan0at1 /dev/wwan0at0; do
|
if [ "$PREFERRED_SIM_SLOT" = "2" ]; then
|
||||||
|
at_candidates="$port /dev/wwan0at1 /dev/wwan0at0"
|
||||||
|
else
|
||||||
|
at_candidates="$port /dev/wwan0at0 /dev/wwan0at1"
|
||||||
|
fi
|
||||||
|
for candidate in $at_candidates; do
|
||||||
case "$candidate" in
|
case "$candidate" in
|
||||||
wwan0at0|wwan0at1)
|
wwan0at0|wwan0at1)
|
||||||
dev="/dev/$candidate"
|
dev="/dev/$candidate"
|
||||||
@@ -518,7 +772,7 @@ case "$cmd" in
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
if [ -n "$dev" ] && [ -c "$dev" ]; then
|
if [ -n "$dev" ] && [ -c "$dev" ]; then
|
||||||
resp="$(timeout 2 sh -c '
|
resp="$(timeout 3 sh -c '
|
||||||
dev="$1"
|
dev="$1"
|
||||||
cmd="$2"
|
cmd="$2"
|
||||||
tmpf="/tmp/at_resp_$$.txt"
|
tmpf="/tmp/at_resp_$$.txt"
|
||||||
@@ -528,7 +782,7 @@ case "$cmd" in
|
|||||||
sleep 0.04
|
sleep 0.04
|
||||||
printf "%s\r\n" "$cmd" > "$dev" 2>/dev/null || true
|
printf "%s\r\n" "$cmd" > "$dev" 2>/dev/null || true
|
||||||
i=0
|
i=0
|
||||||
while [ "$i" -lt 12 ]; do
|
while [ "$i" -lt 16 ]; do
|
||||||
if grep -qE "(^|[[:space:]])(OK|ERROR|\+CME ERROR|\+CMS ERROR)([[:space:]]|$)" "$tmpf" 2>/dev/null; then
|
if grep -qE "(^|[[:space:]])(OK|ERROR|\+CME ERROR|\+CMS ERROR)([[:space:]]|$)" "$tmpf" 2>/dev/null; then
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
@@ -558,6 +812,84 @@ case "$cmd" in
|
|||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
ussd)
|
||||||
|
ussd_mode="${2:-initiate}"
|
||||||
|
shift 2 2>/dev/null || true
|
||||||
|
ussd_code="$*"
|
||||||
|
if [ "$ussd_mode" = "cancel" ]; then
|
||||||
|
mmcli -m any --3gpp-ussd-cancel >/dev/null 2>&1 || true
|
||||||
|
"$0" at auto 'AT+CUSD=2' >/dev/null 2>&1 || true
|
||||||
|
echo "USSD session cancelled."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
if [ -z "$ussd_code" ]; then
|
||||||
|
echo "ERROR: Empty USSD code"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
mm_state="$(mmcli -m any -K 2>/dev/null | awk -F': ' '$1 == "modem.generic.state" {print $2; exit}')"
|
||||||
|
if [ "$mm_state" = "disabled" ] || [ -z "$mm_state" ]; then
|
||||||
|
mmcli -m any -e >/dev/null 2>&1 || true
|
||||||
|
sleep 1
|
||||||
|
fi
|
||||||
|
if [ "$ussd_mode" = "respond" ]; then
|
||||||
|
mm_out="$(mmcli -m any --3gpp-ussd-respond="$ussd_code" 2>&1)"
|
||||||
|
mm_rc=$?
|
||||||
|
else
|
||||||
|
mmcli -m any --3gpp-ussd-cancel >/dev/null 2>&1 || true
|
||||||
|
mm_out="$(mmcli -m any --3gpp-ussd-initiate="$ussd_code" 2>&1)"
|
||||||
|
mm_rc=$?
|
||||||
|
fi
|
||||||
|
if [ "$mm_rc" -eq 0 ] && [ -n "$mm_out" ]; then
|
||||||
|
printf "%s\n" "$mm_out" | sed -e "s/^USSD session initiated; new reply from network: '\(.*\)'$/\1/" -e "s/^USSD response sent; new reply from network: '\(.*\)'$/\1/"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
# Fallback to direct AT+CUSD on the active SIM AT port
|
||||||
|
if [ "$PREFERRED_SIM_SLOT" = "2" ]; then
|
||||||
|
at_candidates="/dev/wwan0at1 /dev/wwan0at0"
|
||||||
|
else
|
||||||
|
at_candidates="/dev/wwan0at0 /dev/wwan0at1"
|
||||||
|
fi
|
||||||
|
for dev in $at_candidates; do
|
||||||
|
[ -c "$dev" ] || continue
|
||||||
|
cusd_out="$(timeout 12 sh -c '
|
||||||
|
dev="$1"
|
||||||
|
code="$2"
|
||||||
|
tmpf="/tmp/ussd_resp_$$.txt"
|
||||||
|
rm -f "$tmpf"
|
||||||
|
cat "$dev" > "$tmpf" 2>/dev/null &
|
||||||
|
rpid=$!
|
||||||
|
sleep 0.05
|
||||||
|
printf "AT+CSCS=\"GSM\";+CUSD=1,\"%s\",15\r\n" "$code" > "$dev" 2>/dev/null || true
|
||||||
|
i=0
|
||||||
|
while [ "$i" -lt 80 ]; do
|
||||||
|
if grep -qE "\+CUSD:[[:space:]]*[0-9]+" "$tmpf" 2>/dev/null; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if grep -qE "(^|[[:space:]])(\+CME ERROR|\+CMS ERROR|ERROR)([[:space:]]|$)" "$tmpf" 2>/dev/null; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 0.1
|
||||||
|
i=$((i + 1))
|
||||||
|
done
|
||||||
|
kill "$rpid" 2>/dev/null || true
|
||||||
|
wait "$rpid" 2>/dev/null || true
|
||||||
|
tr -d "\r" < "$tmpf" 2>/dev/null || true
|
||||||
|
rm -f "$tmpf"
|
||||||
|
' _ "$dev" "$ussd_code" 2>/dev/null || true)"
|
||||||
|
cusd_msg="$(printf "%s\n" "$cusd_out" | sed -n 's/.*+CUSD:[[:space:]]*[0-9]*,[[:space:]]*"\([^"]*\)".*/\1/p' | tail -n1)"
|
||||||
|
if [ -n "$cusd_msg" ]; then
|
||||||
|
printf "%s\n" "$cusd_msg"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ -n "$mm_out" ]; then
|
||||||
|
printf "%s\n" "$mm_out"
|
||||||
|
else
|
||||||
|
echo "ERROR: USSD request failed"
|
||||||
|
fi
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
sim-contacts-import)
|
sim-contacts-import)
|
||||||
req_slot="${2:-auto}"
|
req_slot="${2:-auto}"
|
||||||
if ! wait_for_qmicli_modem 3; then
|
if ! wait_for_qmicli_modem 3; then
|
||||||
@@ -688,8 +1020,8 @@ case "$cmd" in
|
|||||||
# Method 2: Direct QMI UIM EF_ADN (3F00:7F10:6F3A) record fallback
|
# Method 2: Direct QMI UIM EF_ADN (3F00:7F10:6F3A) record fallback
|
||||||
if [ ! -s "$tmp_contacts" ]; then
|
if [ ! -s "$tmp_contacts" ]; then
|
||||||
adn_attr="$($QMICLI_MODEM --uim-get-file-attributes=0x3F00,0x7F10,0x6F3A 2>/dev/null || true)"
|
adn_attr="$($QMICLI_MODEM --uim-get-file-attributes=0x3F00,0x7F10,0x6F3A 2>/dev/null || true)"
|
||||||
reclen="$(printf "%s\n" "$adn_attr" | awk -F"'" '/Record length:/ {print $2 + 0; exit}')"
|
reclen="$(printf "%s\n" "$adn_attr" | awk '/Record (size|length):/ {gsub(/[^0-9]/, "", $NF); print $NF + 0; exit}')"
|
||||||
reccount="$(printf "%s\n" "$adn_attr" | awk -F"'" '/Record count:/ {print $2 + 0; exit}')"
|
reccount="$(printf "%s\n" "$adn_attr" | awk '/Record count:/ {gsub(/[^0-9]/, "", $NF); print $NF + 0; exit}')"
|
||||||
if [ -n "$reclen" ] && [ -n "$reccount" ] && [ "$reclen" -ge 14 ] 2>/dev/null && [ "$reccount" -ge 1 ] 2>/dev/null; then
|
if [ -n "$reclen" ] && [ -n "$reccount" ] && [ "$reclen" -ge 14 ] 2>/dev/null && [ "$reccount" -ge 1 ] 2>/dev/null; then
|
||||||
if [ "$reccount" -gt 250 ]; then
|
if [ "$reccount" -gt 250 ]; then
|
||||||
reccount=250
|
reccount=250
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
horizontal_padding = 6
|
horizontal_padding = 6
|
||||||
frame_width = 2
|
frame_width = 2
|
||||||
frame_color = "#005577"
|
frame_color = "#005577"
|
||||||
idle_threshold = 120
|
idle_threshold = 0
|
||||||
font = Fira Code 9.5
|
font = Fira Code 9.5
|
||||||
markup = full
|
markup = full
|
||||||
max_icon_size = 24
|
max_icon_size = 24
|
||||||
@@ -22,16 +22,16 @@
|
|||||||
[urgency_low]
|
[urgency_low]
|
||||||
background = "#222222"
|
background = "#222222"
|
||||||
foreground = "#cccccc"
|
foreground = "#cccccc"
|
||||||
timeout = 8
|
timeout = 5
|
||||||
|
|
||||||
[urgency_normal]
|
[urgency_normal]
|
||||||
background = "#1c1c1c"
|
background = "#1c1c1c"
|
||||||
foreground = "#ffffff"
|
foreground = "#ffffff"
|
||||||
frame_color = "#005577"
|
frame_color = "#005577"
|
||||||
timeout = 12
|
timeout = 8
|
||||||
|
|
||||||
[urgency_critical]
|
[urgency_critical]
|
||||||
background = "#900000"
|
background = "#900000"
|
||||||
foreground = "#ffffff"
|
foreground = "#ffffff"
|
||||||
frame_color = "#ff0000"
|
frame_color = "#ff0000"
|
||||||
timeout = 0
|
timeout = 10
|
||||||
|
|||||||
@@ -15,22 +15,68 @@ newstate="$2"
|
|||||||
|
|
||||||
sxmo_debug "$2 (old: $1 [reason: $3])"
|
sxmo_debug "$2 (old: $1 [reason: $3])"
|
||||||
|
|
||||||
case "$newstate" in
|
open_sim_unlock_ui() {
|
||||||
"locked")
|
(
|
||||||
sxmo_log "State is locked. Opening SIM PIN/PUK unlock dialog."
|
i=0
|
||||||
|
while [ "$i" -lt 40 ] && [ ! -p /tmp/dwm_plugin_modem.fifo ]; do
|
||||||
|
sleep 0.2
|
||||||
|
i=$((i + 1))
|
||||||
|
done
|
||||||
if command -v xmodem >/dev/null 2>&1; then
|
if command -v xmodem >/dev/null 2>&1; then
|
||||||
xmodem unlock >/dev/null 2>&1 &
|
DISPLAY="${DISPLAY:-:0}" xmodem unlock >/dev/null 2>&1 &
|
||||||
elif ! pgrep -f "sxmo_unlocksim.sh" >/dev/null; then
|
elif ! pgrep -f "sxmo_unlocksim.sh" >/dev/null; then
|
||||||
sxmo_unlocksim.sh &
|
sxmo_unlocksim.sh &
|
||||||
fi
|
fi
|
||||||
|
) &
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$newstate" in
|
||||||
|
"locked")
|
||||||
|
sxmo_log "State is locked. Opening SIM PIN/PUK unlock dialog."
|
||||||
|
open_sim_unlock_ui
|
||||||
|
;;
|
||||||
|
"failed")
|
||||||
|
sxmo_log "State is failed. Checking QMI UIM status for SIM2/PIN lock."
|
||||||
|
(
|
||||||
|
uim_st="$(doas -n /usr/libexec/msm-modem-uim-selection status 2>/dev/null || /usr/libexec/msm-modem-uim-selection status 2>/dev/null || true)"
|
||||||
|
if printf "%s\n" "$uim_st" | grep -qE "SLOT[12]_PIN1_STATE=(enabled-not-verified|blocked)|SLOT[12]_APP_STATE=(pin1|puk1)"; then
|
||||||
|
sxmo_log "QMI UIM reports locked SIM while ModemManager state is failed; opening unlock UI."
|
||||||
|
open_sim_unlock_ui
|
||||||
|
elif printf "%s\n" "$uim_st" | grep -qE "SLOT[12]_STATE=present" && printf "%s\n" "$uim_st" | grep -q "^PRIMARY_GW_SLOT=0$"; then
|
||||||
|
now_ts="$(date +%s 2>/dev/null || echo 0)"
|
||||||
|
last_ts="$(cat /tmp/sxmo_modem_reprov.stamp 2>/dev/null || echo 0)"
|
||||||
|
if [ $((now_ts - last_ts)) -ge 25 ]; then
|
||||||
|
echo "$now_ts" > /tmp/sxmo_modem_reprov.stamp
|
||||||
|
sxmo_log "Unprovisioned SIM detected in failed state; running msm-modem-uim-selection boot."
|
||||||
|
doas -n /usr/libexec/msm-modem-uim-selection boot >/dev/null 2>&1 || true
|
||||||
|
sxmo_hook_statusbar.sh modem >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
) &
|
||||||
|
;;
|
||||||
|
"disabled")
|
||||||
|
sxmo_log "State is disabled. Enabling modem and registering on network."
|
||||||
|
(
|
||||||
|
mmcli -m any -e >/dev/null 2>&1 || true
|
||||||
|
sleep 1
|
||||||
|
mmcli -m any --3gpp-register-home >/dev/null 2>&1 || true
|
||||||
|
sxmo_hook_statusbar.sh modem >/dev/null 2>&1 || true
|
||||||
|
) &
|
||||||
;;
|
;;
|
||||||
"enabling")
|
"enabling")
|
||||||
sxmo_log "State is enabling. Clearing stale call files."
|
sxmo_log "State is enabling. Clearing stale call files."
|
||||||
rm "$XDG_RUNTIME_DIR"/sxmo_calls/* 2>/dev/null || true
|
rm "$XDG_RUNTIME_DIR"/sxmo_calls/* 2>/dev/null || true
|
||||||
rm -f "$SXMO_NOTIFDIR"/incomingcall* 2>/dev/null || true
|
rm -f "$SXMO_NOTIFDIR"/incomingcall* 2>/dev/null || true
|
||||||
;;
|
;;
|
||||||
"registered")
|
"enabled")
|
||||||
sxmo_log "State is registered. Checking for calls and messages."
|
sxmo_log "State is enabled. Requesting 3GPP network registration."
|
||||||
|
(
|
||||||
|
mmcli -m any --3gpp-register-home >/dev/null 2>&1 || true
|
||||||
|
sxmo_hook_statusbar.sh modem >/dev/null 2>&1 || true
|
||||||
|
) &
|
||||||
|
;;
|
||||||
|
"registered"|"connected")
|
||||||
|
sxmo_log "State is $newstate. Checking for calls and messages."
|
||||||
|
|
||||||
# kill the pin-entry dmenu if still open
|
# kill the pin-entry dmenu if still open
|
||||||
pkill -f sxmo_unlocksim.sh 2>/dev/null || true
|
pkill -f sxmo_unlocksim.sh 2>/dev/null || true
|
||||||
|
|||||||
@@ -59,6 +59,13 @@ set_modem() {
|
|||||||
MODEMSTATE="$(printf %s "$MMCLI" | jq -r .modem.generic.state)"
|
MODEMSTATE="$(printf %s "$MMCLI" | jq -r .modem.generic.state)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$MODEMSTATE" = "failed" ] || [ "$MODEMSTATE" = "nomodem" ]; then
|
||||||
|
uim_st="$(doas -n /usr/libexec/msm-modem-uim-selection status 2>/dev/null || /usr/libexec/msm-modem-uim-selection status 2>/dev/null || true)"
|
||||||
|
if printf "%s\n" "$uim_st" | grep -qE "SLOT[12]_PIN1_STATE=(enabled-not-verified|blocked)|SLOT[12]_APP_STATE=(pin1|puk1)"; then
|
||||||
|
MODEMSTATE="locked"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
case "$MODEMSTATE" in
|
case "$MODEMSTATE" in
|
||||||
nomodem)
|
nomodem)
|
||||||
fgcolor=red
|
fgcolor=red
|
||||||
@@ -119,7 +126,7 @@ set_modem() {
|
|||||||
sxmobar -a -f "$fgcolor" -b "$bgcolor" -t "$style" \
|
sxmobar -a -f "$fgcolor" -b "$bgcolor" -t "$style" \
|
||||||
modem-state 10 "$MODEMSTATECMP"
|
modem-state 10 "$MODEMSTATECMP"
|
||||||
|
|
||||||
if [ "$MODEMSTATE" = nomodem ]; then
|
if [ "$MODEMSTATE" = nomodem ] || [ "$MODEMSTATE" = locked ] || [ "$MODEMSTATE" = failed ] || [ "$MODEMSTATE" = unknown ]; then
|
||||||
sxmobar -d modem-tech
|
sxmobar -d modem-tech
|
||||||
sxmobar -d modem-signal
|
sxmobar -d modem-signal
|
||||||
return
|
return
|
||||||
@@ -131,7 +138,7 @@ set_modem() {
|
|||||||
style=normal
|
style=normal
|
||||||
|
|
||||||
# see https://www.freedesktop.org/software/ModemManager/api/latest/ModemManager-Flags-and-Enumerations.html#MMModemAccessTechnology
|
# see https://www.freedesktop.org/software/ModemManager/api/latest/ModemManager-Flags-and-Enumerations.html#MMModemAccessTechnology
|
||||||
USEDTECHS="$(printf %s "$MMCLI" | jq -r '.modem.generic."access-technologies"[]')"
|
USEDTECHS="$(printf %s "$MMCLI" | jq -r '.modem.generic."access-technologies"[]? // empty' 2>/dev/null)"
|
||||||
case "$USEDTECHS" in
|
case "$USEDTECHS" in
|
||||||
*5gnr*)
|
*5gnr*)
|
||||||
MODEMTECHCMP="$icon_modem_fiveg"
|
MODEMTECHCMP="$icon_modem_fiveg"
|
||||||
@@ -178,7 +185,10 @@ set_modem() {
|
|||||||
|
|
||||||
case "$MODEMSTATE" in
|
case "$MODEMSTATE" in
|
||||||
registered|connected|connecting|disconnecting)
|
registered|connected|connecting|disconnecting)
|
||||||
MODEMSIGNAL="$(printf %s "$MMCLI" | jq -r '.modem.generic."signal-quality".value')"
|
MODEMSIGNAL="$(printf %s "$MMCLI" | jq -r '.modem.generic."signal-quality".value // 0' 2>/dev/null)"
|
||||||
|
case "$MODEMSIGNAL" in
|
||||||
|
''|*[!0-9]*) MODEMSIGNAL=0 ;;
|
||||||
|
esac
|
||||||
if [ "$MODEMSIGNAL" -lt 33 ]; then
|
if [ "$MODEMSIGNAL" -lt 33 ]; then
|
||||||
MODEMSIGNALCMP="$icon_modem_signal_1"
|
MODEMSIGNALCMP="$icon_modem_signal_1"
|
||||||
elif [ "$MODEMSIGNAL" -lt 66 ]; then
|
elif [ "$MODEMSIGNAL" -lt 66 ]; then
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -62,12 +62,15 @@ struct SimSlotInfo {
|
|||||||
|
|
||||||
bool needsPin() const {
|
bool needsPin() const {
|
||||||
return state == "present" &&
|
return state == "present" &&
|
||||||
(pin1State == "enabled-not-verified" || appState == "pin1");
|
(pin1State == "enabled-not-verified" ||
|
||||||
|
appState.rfind("pin1", 0) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool needsPuk() const {
|
bool needsPuk() const {
|
||||||
return state == "present" &&
|
return state == "present" &&
|
||||||
(pin1State == "blocked" || appState == "puk1");
|
(pin1State == "blocked" ||
|
||||||
|
appState.rfind("puk1", 0) == 0 ||
|
||||||
|
appState == "pin1-blocked");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isPinEnabled() const {
|
bool isPinEnabled() const {
|
||||||
@@ -88,6 +91,13 @@ struct ModemStatusData {
|
|||||||
std::string mmFailedReason;
|
std::string mmFailedReason;
|
||||||
std::string mmPowerState = "off";
|
std::string mmPowerState = "off";
|
||||||
std::string mmUnlockRequired;
|
std::string mmUnlockRequired;
|
||||||
|
std::string mmRegState;
|
||||||
|
std::string nasRegState;
|
||||||
|
std::string nasOperator;
|
||||||
|
std::string nasMcc;
|
||||||
|
std::string nasMnc;
|
||||||
|
std::string nasRoaming;
|
||||||
|
std::string nasRadio;
|
||||||
int mmPinRetries = -1;
|
int mmPinRetries = -1;
|
||||||
int mmPukRetries = -1;
|
int mmPukRetries = -1;
|
||||||
std::string operatorName;
|
std::string operatorName;
|
||||||
@@ -103,6 +113,56 @@ struct ModemStatusData {
|
|||||||
std::string simOperatorName;
|
std::string simOperatorName;
|
||||||
std::string currentModes;
|
std::string currentModes;
|
||||||
int modePresetIdx = 0;
|
int modePresetIdx = 0;
|
||||||
|
|
||||||
|
bool isNetworkRegistered() const {
|
||||||
|
return mmRegState == "home" || mmRegState == "roaming" ||
|
||||||
|
nasRegState == "registered" ||
|
||||||
|
mmState == "registered" || mmState == "connected";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isNetworkSearching() const {
|
||||||
|
return mmRegState == "searching" || nasRegState == "searching" ||
|
||||||
|
mmState == "searching" || mmState == "enabling" ||
|
||||||
|
mmState == "connecting";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string regStatusLabel() const {
|
||||||
|
if (slots[0].needsPuk() || slots[1].needsPuk() ||
|
||||||
|
mmUnlockRequired == "sim-puk") {
|
||||||
|
return "SIM PUK Required";
|
||||||
|
}
|
||||||
|
if (slots[0].needsPin() || slots[1].needsPin() ||
|
||||||
|
mmUnlockRequired == "sim-pin" || mmState == "locked") {
|
||||||
|
return "SIM PIN Required";
|
||||||
|
}
|
||||||
|
if (mmRegState == "home" ||
|
||||||
|
(nasRegState == "registered" && nasRoaming != "on")) {
|
||||||
|
return "Registered (Home)";
|
||||||
|
}
|
||||||
|
if (mmRegState == "roaming" ||
|
||||||
|
(nasRegState == "registered" && nasRoaming == "on")) {
|
||||||
|
return "Registered (Roaming)";
|
||||||
|
}
|
||||||
|
if (mmState == "connected" || mmState == "registered") {
|
||||||
|
return "Registered";
|
||||||
|
}
|
||||||
|
if (isNetworkSearching()) {
|
||||||
|
return "Searching...";
|
||||||
|
}
|
||||||
|
if (mmRegState == "denied" || nasRegState == "registration-denied") {
|
||||||
|
return "Registration Denied";
|
||||||
|
}
|
||||||
|
if (slots[0].state != "present" && slots[1].state != "present") {
|
||||||
|
return "No SIM Inserted";
|
||||||
|
}
|
||||||
|
if (primaryGwSlot == 0) {
|
||||||
|
return "SIM Not Activated";
|
||||||
|
}
|
||||||
|
if (mmState == "disabled") {
|
||||||
|
return "Modem Disabled";
|
||||||
|
}
|
||||||
|
return "Not Registered";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RadioModePreset {
|
struct RadioModePreset {
|
||||||
@@ -201,6 +261,12 @@ ModemStatusData queryModemAndSimStatus() {
|
|||||||
if (!uimKv["PRIMARY_GW_SLOT"].empty()) {
|
if (!uimKv["PRIMARY_GW_SLOT"].empty()) {
|
||||||
d.primaryGwSlot = std::atoi(uimKv["PRIMARY_GW_SLOT"].c_str());
|
d.primaryGwSlot = std::atoi(uimKv["PRIMARY_GW_SLOT"].c_str());
|
||||||
}
|
}
|
||||||
|
d.nasRegState = uimKv["NAS_REG_STATE"];
|
||||||
|
d.nasOperator = uimKv["NAS_OPERATOR"];
|
||||||
|
d.nasMcc = uimKv["NAS_MCC"];
|
||||||
|
d.nasMnc = uimKv["NAS_MNC"];
|
||||||
|
d.nasRoaming = uimKv["NAS_ROAMING"];
|
||||||
|
d.nasRadio = uimKv["NAS_RADIO"];
|
||||||
|
|
||||||
for (int i = 0; i < 2; ++i) {
|
for (int i = 0; i < 2; ++i) {
|
||||||
std::string pfx = "SLOT" + std::to_string(i + 1) + "_";
|
std::string pfx = "SLOT" + std::to_string(i + 1) + "_";
|
||||||
@@ -244,6 +310,7 @@ ModemStatusData queryModemAndSimStatus() {
|
|||||||
d.mmFailedReason = cleanMmVal(mmKv["modem.generic.state-failed-reason"]);
|
d.mmFailedReason = cleanMmVal(mmKv["modem.generic.state-failed-reason"]);
|
||||||
d.mmPowerState = cleanMmVal(mmKv["modem.generic.power-state"]);
|
d.mmPowerState = cleanMmVal(mmKv["modem.generic.power-state"]);
|
||||||
d.mmUnlockRequired = cleanMmVal(mmKv["modem.generic.unlock-required"]);
|
d.mmUnlockRequired = cleanMmVal(mmKv["modem.generic.unlock-required"]);
|
||||||
|
d.mmRegState = cleanMmVal(mmKv["modem.3gpp.registration-state"]);
|
||||||
d.operatorName = cleanMmVal(mmKv["modem.3gpp.operator-name"]);
|
d.operatorName = cleanMmVal(mmKv["modem.3gpp.operator-name"]);
|
||||||
d.operatorCode = cleanMmVal(mmKv["modem.3gpp.operator-code"]);
|
d.operatorCode = cleanMmVal(mmKv["modem.3gpp.operator-code"]);
|
||||||
d.accessTech = cleanMmVal(mmKv["modem.generic.access-technologies.value[1]"]);
|
d.accessTech = cleanMmVal(mmKv["modem.generic.access-technologies.value[1]"]);
|
||||||
@@ -309,6 +376,16 @@ ModemStatusData queryModemAndSimStatus() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (d.operatorName.empty() && !d.nasOperator.empty()) {
|
||||||
|
d.operatorName = d.nasOperator;
|
||||||
|
}
|
||||||
|
if (d.operatorCode.empty() && !d.nasMcc.empty() && !d.nasMnc.empty()) {
|
||||||
|
d.operatorCode = d.nasMcc + d.nasMnc;
|
||||||
|
}
|
||||||
|
if (d.accessTech.empty() && !d.nasRadio.empty() && d.nasRadio != "none") {
|
||||||
|
d.accessTech = d.nasRadio;
|
||||||
|
}
|
||||||
|
|
||||||
// Sync ModemManager lock info into active slot if QMI didn't report retries
|
// Sync ModemManager lock info into active slot if QMI didn't report retries
|
||||||
int actIdx = (d.primaryGwSlot >= 1 && d.primaryGwSlot <= 2)
|
int actIdx = (d.primaryGwSlot >= 1 && d.primaryGwSlot <= 2)
|
||||||
? (d.primaryGwSlot - 1)
|
? (d.primaryGwSlot - 1)
|
||||||
@@ -395,8 +472,8 @@ int runModemApp(int argc, char** argv) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeIntFile(daemonPidPath, static_cast<int>(::getpid()));
|
|
||||||
int fifoFd = setupPluginDaemonFifo("modem");
|
int fifoFd = setupPluginDaemonFifo("modem");
|
||||||
|
writeIntFile(daemonPidPath, static_cast<int>(::getpid()));
|
||||||
|
|
||||||
struct sigaction sa {};
|
struct sigaction sa {};
|
||||||
sa.sa_handler = handleSignal;
|
sa.sa_handler = handleSignal;
|
||||||
@@ -702,10 +779,24 @@ int runModemApp(int argc, char** argv) {
|
|||||||
line2 = "LOCKED (Enter PIN)";
|
line2 = "LOCKED (Enter PIN)";
|
||||||
line2Col = &colOrange;
|
line2Col = &colOrange;
|
||||||
} else if (s.isActiveProvisioned) {
|
} else if (s.isActiveProvisioned) {
|
||||||
std::string op = status.operatorName.empty() ? "Ready" : status.operatorName;
|
std::string reg = status.regStatusLabel();
|
||||||
if (!status.ownNumber.empty()) op += " " + status.ownNumber;
|
if (!status.operatorName.empty()) {
|
||||||
line2 = op;
|
reg += " - " + status.operatorName;
|
||||||
line2Col = &colGreen;
|
}
|
||||||
|
if (!status.accessTech.empty()) {
|
||||||
|
reg += " [" + status.accessTech + "]";
|
||||||
|
}
|
||||||
|
line2 = reg;
|
||||||
|
if (status.isNetworkRegistered()) {
|
||||||
|
line2Col = &colGreen;
|
||||||
|
} else if (status.isNetworkSearching()) {
|
||||||
|
line2Col = &colOrange;
|
||||||
|
} else {
|
||||||
|
line2Col = &colRed;
|
||||||
|
}
|
||||||
|
} else if (status.primaryGwSlot == 0) {
|
||||||
|
line2 = "Present (Unactivated - Press Select)";
|
||||||
|
line2Col = &colOrange;
|
||||||
} else {
|
} else {
|
||||||
line2 = "Present (Standby " + s.appType + ")";
|
line2 = "Present (Standby " + s.appType + ")";
|
||||||
line2Col = &colBlue;
|
line2Col = &colBlue;
|
||||||
@@ -726,6 +817,9 @@ int runModemApp(int argc, char** argv) {
|
|||||||
else if (pState == "blocked") pState = "PUK Req";
|
else if (pState == "blocked") pState = "PUK Req";
|
||||||
line3 = pState + " (PIN:" + std::to_string(s.pin1Retries) +
|
line3 = pState + " (PIN:" + std::to_string(s.pin1Retries) +
|
||||||
" PUK:" + std::to_string(s.puk1Retries) + ")";
|
" PUK:" + std::to_string(s.puk1Retries) + ")";
|
||||||
|
if (s.isActiveProvisioned && !status.ownNumber.empty()) {
|
||||||
|
line3 += " " + status.ownNumber;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
line3 = "Insert nano-SIM & restart/switch";
|
line3 = "Insert nano-SIM & restart/switch";
|
||||||
}
|
}
|
||||||
@@ -736,8 +830,18 @@ int runModemApp(int argc, char** argv) {
|
|||||||
// Quick Action Rows below the 2 SIM cards (4 rows, 24px each)
|
// Quick Action Rows below the 2 SIM cards (4 rows, 24px each)
|
||||||
int actSlot = (simRowSel == 1) ? 2 : 1;
|
int actSlot = (simRowSel == 1) ? 2 : 1;
|
||||||
int otherSlot = (status.preferredSlot == 1) ? 2 : 1;
|
int otherSlot = (status.preferredSlot == 1) ? 2 : 1;
|
||||||
|
if (status.primaryGwSlot == 0) {
|
||||||
|
if (status.slots[1].state == "present" && status.slots[0].state != "present") {
|
||||||
|
otherSlot = 2;
|
||||||
|
} else if (status.slots[0].state == "present" && status.slots[1].state != "present") {
|
||||||
|
otherSlot = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
std::string quickRows[4] = {
|
std::string quickRows[4] = {
|
||||||
std::string(kIconRefresh) + " Switch Active to SIM " + std::to_string(otherSlot),
|
std::string(kIconRefresh) +
|
||||||
|
(status.primaryGwSlot == 0
|
||||||
|
? (" Activate SIM " + std::to_string(otherSlot))
|
||||||
|
: (" Switch Active to SIM " + std::to_string(otherSlot))),
|
||||||
std::string(kIconUnlock) + " Unlock SIM (PIN / PUK)",
|
std::string(kIconUnlock) + " Unlock SIM (PIN / PUK)",
|
||||||
std::string(kIconLock) + " Enable / Disable SIM PIN",
|
std::string(kIconLock) + " Enable / Disable SIM PIN",
|
||||||
std::string(kIconKey) + " Change SIM PIN Code",
|
std::string(kIconKey) + " Change SIM PIN Code",
|
||||||
@@ -762,29 +866,31 @@ int runModemApp(int argc, char** argv) {
|
|||||||
XSetForeground(dpy, gc, pt.spec.border);
|
XSetForeground(dpy, gc, pt.spec.border);
|
||||||
XDrawRectangle(dpy, pix, gc, 4, contentY, kWinWidth - 9, 101);
|
XDrawRectangle(dpy, pix, gc, 4, contentY, kWinWidth - 9, 101);
|
||||||
|
|
||||||
std::string stStr = status.mmPresent ? status.mmState : "nomodem";
|
std::string regStr = status.regStatusLabel();
|
||||||
if (!status.mmFailedReason.empty()) {
|
|
||||||
stStr += " (" + status.mmFailedReason + ")";
|
|
||||||
}
|
|
||||||
XftColor* stCol = &colRed;
|
XftColor* stCol = &colRed;
|
||||||
if (status.mmState == "connected" || status.mmState == "registered") {
|
if (status.isNetworkRegistered()) {
|
||||||
stCol = &colGreen;
|
stCol = &colGreen;
|
||||||
} else if (status.mmState == "searching" || status.mmState == "connecting") {
|
} else if (status.isNetworkSearching()) {
|
||||||
stCol = &colOrange;
|
stCol = &colOrange;
|
||||||
}
|
}
|
||||||
drawPango(layoutMain, stCol, 10, contentY + 2, 22,
|
drawPango(layoutMain, stCol, 10, contentY + 2, 22,
|
||||||
"State: " + stStr, 185);
|
"Net: " + regStr, 185);
|
||||||
drawSignalBars(kWinWidth - 32, contentY + 6, status.signalQuality);
|
drawSignalBars(kWinWidth - 32, contentY + 6, status.signalQuality);
|
||||||
|
|
||||||
std::string opLine = "Operator: " +
|
std::string opLine = "Operator: " +
|
||||||
(status.operatorName.empty() ? "--" : status.operatorName);
|
(status.operatorName.empty() ? "--" : status.operatorName);
|
||||||
|
if (!status.operatorCode.empty() &&
|
||||||
|
status.operatorName != status.operatorCode) {
|
||||||
|
opLine += " (" + status.operatorCode + ")";
|
||||||
|
}
|
||||||
if (!status.accessTech.empty()) {
|
if (!status.accessTech.empty()) {
|
||||||
opLine += " [" + status.accessTech + "]";
|
opLine += " [" + status.accessTech + "]";
|
||||||
}
|
}
|
||||||
drawPango(layoutSmall, &colLight, 10, contentY + 24, 18, opLine, 220);
|
drawPango(layoutSmall, &colLight, 10, contentY + 24, 18, opLine, 220);
|
||||||
|
|
||||||
std::string sigLine = "Signal: " + std::to_string(status.signalQuality) +
|
std::string stStr = status.mmPresent ? status.mmState : "nomodem";
|
||||||
"% | Slot: SIM " +
|
std::string sigLine = "Modem: " + stStr + " | Sig: " +
|
||||||
|
std::to_string(status.signalQuality) + "% | SIM " +
|
||||||
(status.primaryGwSlot > 0 ? std::to_string(status.primaryGwSlot) : "--");
|
(status.primaryGwSlot > 0 ? std::to_string(status.primaryGwSlot) : "--");
|
||||||
drawPango(layoutSmall, &colLight, 10, contentY + 42, 18, sigLine, 220);
|
drawPango(layoutSmall, &colLight, 10, contentY + 42, 18, sigLine, 220);
|
||||||
|
|
||||||
@@ -1090,6 +1196,15 @@ int runModemApp(int argc, char** argv) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
auto showWindow = [&](const std::string& arg = "") {
|
auto showWindow = [&](const std::string& arg = "") {
|
||||||
|
std::string a = toLowerStr(trimStr(arg));
|
||||||
|
if (visible &&
|
||||||
|
(modal == ModalMode::VerifyPin || modal == ModalMode::UnblockPuk) &&
|
||||||
|
(a == "unlock" || a == "pin" || a == "puk")) {
|
||||||
|
XRaiseWindow(dpy, win);
|
||||||
|
grabKeys();
|
||||||
|
render();
|
||||||
|
return;
|
||||||
|
}
|
||||||
closeOtherPlugins("modem");
|
closeOtherPlugins("modem");
|
||||||
refreshData(true);
|
refreshData(true);
|
||||||
applyOpenArg(arg);
|
applyOpenArg(arg);
|
||||||
@@ -1308,16 +1423,36 @@ int runModemApp(int argc, char** argv) {
|
|||||||
|
|
||||||
auto triggerSimRowAction = [&](int row) {
|
auto triggerSimRowAction = [&](int row) {
|
||||||
if (row == 0 || row == 1) {
|
if (row == 0 || row == 1) {
|
||||||
targetSlot = row + 1;
|
int sNum = row + 1;
|
||||||
actionSel = 0;
|
const auto& s = status.slots[row];
|
||||||
modal = ModalMode::SimActions;
|
if (s.needsPin() || s.needsPuk()) {
|
||||||
|
openPinOrPukModalForSlot(sNum);
|
||||||
|
} else if (s.state == "present" && !s.isActiveProvisioned) {
|
||||||
|
switchSimSlotNow(sNum);
|
||||||
|
} else {
|
||||||
|
targetSlot = sNum;
|
||||||
|
actionSel = 0;
|
||||||
|
modal = ModalMode::SimActions;
|
||||||
|
}
|
||||||
} else if (row == 2) {
|
} else if (row == 2) {
|
||||||
int otherSlot = (status.preferredSlot == 1) ? 2 : 1;
|
int otherSlot = (status.preferredSlot == 1) ? 2 : 1;
|
||||||
|
if (status.primaryGwSlot == 0) {
|
||||||
|
if (status.slots[1].state == "present" && status.slots[0].state != "present") {
|
||||||
|
otherSlot = 2;
|
||||||
|
} else if (status.slots[0].state == "present" && status.slots[1].state != "present") {
|
||||||
|
otherSlot = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
switchSimSlotNow(otherSlot);
|
switchSimSlotNow(otherSlot);
|
||||||
} else if (row == 3) {
|
} else if (row == 3) {
|
||||||
int slot = (status.primaryGwSlot >= 1 && status.primaryGwSlot <= 2)
|
int slot = (status.primaryGwSlot >= 1 && status.primaryGwSlot <= 2)
|
||||||
? status.primaryGwSlot
|
? status.primaryGwSlot
|
||||||
: status.preferredSlot;
|
: status.preferredSlot;
|
||||||
|
if (status.slots[0].needsPin() || status.slots[0].needsPuk()) {
|
||||||
|
slot = 1;
|
||||||
|
} else if (status.slots[1].needsPin() || status.slots[1].needsPuk()) {
|
||||||
|
slot = 2;
|
||||||
|
}
|
||||||
openPinOrPukModalForSlot(slot);
|
openPinOrPukModalForSlot(slot);
|
||||||
} else if (row == 4) {
|
} else if (row == 4) {
|
||||||
targetSlot = (status.primaryGwSlot >= 1 && status.primaryGwSlot <= 2)
|
targetSlot = (status.primaryGwSlot >= 1 && status.primaryGwSlot <= 2)
|
||||||
@@ -1446,14 +1581,18 @@ int runModemApp(int argc, char** argv) {
|
|||||||
ussdResponse.clear();
|
ussdResponse.clear();
|
||||||
ussdWaitingReply = false;
|
ussdWaitingReply = false;
|
||||||
} else if (radioRowSel == 2) {
|
} else if (radioRowSel == 2) {
|
||||||
bool powerOn = (status.mmPowerState == "on" ||
|
bool powerOn = (status.mmPowerState == "on" &&
|
||||||
status.mmState == "registered" ||
|
status.mmState != "disabled" &&
|
||||||
status.mmState == "connected" ||
|
status.mmState != "failed");
|
||||||
status.mmState == "searching");
|
|
||||||
setBanner(powerOn ? "Disabling modem..." : "Enabling modem...");
|
setBanner(powerOn ? "Disabling modem..." : "Enabling modem...");
|
||||||
render();
|
render();
|
||||||
runCaptureCmd(powerOn ? "mmcli -m any -d >/dev/null 2>&1"
|
if (powerOn) {
|
||||||
: "mmcli -m any -e >/dev/null 2>&1");
|
runCaptureCmd("mmcli -m any -d >/dev/null 2>&1");
|
||||||
|
} else {
|
||||||
|
runCaptureCmd(
|
||||||
|
"doas -n /usr/libexec/msm-modem-uim-selection boot >/dev/null 2>&1 "
|
||||||
|
"|| mmcli -m any -e >/dev/null 2>&1");
|
||||||
|
}
|
||||||
refreshData(false);
|
refreshData(false);
|
||||||
runAsyncCmd("sxmo_hook_statusbar.sh modem >/dev/null 2>&1");
|
runAsyncCmd("sxmo_hook_statusbar.sh modem >/dev/null 2>&1");
|
||||||
} else if (radioRowSel == 3) {
|
} else if (radioRowSel == 3) {
|
||||||
@@ -1494,6 +1633,9 @@ int runModemApp(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int autoCheckStage = isPreload ? 0 : 2;
|
||||||
|
int64_t nextAutoCheckMs = nowMs() + 2500;
|
||||||
|
|
||||||
if (!isPreload) {
|
if (!isPreload) {
|
||||||
showWindow(openArg);
|
showWindow(openArg);
|
||||||
}
|
}
|
||||||
@@ -1841,6 +1983,28 @@ int runModemApp(int argc, char** argv) {
|
|||||||
timeoutMs = static_cast<int>(rRem);
|
timeoutMs = static_cast<int>(rRem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (autoCheckStage < 2) {
|
||||||
|
int64_t aRem = nextAutoCheckMs - now;
|
||||||
|
if (aRem <= 0) {
|
||||||
|
++autoCheckStage;
|
||||||
|
nextAutoCheckMs = now + 4500;
|
||||||
|
refreshData(false);
|
||||||
|
if (status.slots[0].needsPin() || status.slots[0].needsPuk() ||
|
||||||
|
status.slots[1].needsPin() || status.slots[1].needsPuk() ||
|
||||||
|
status.mmState == "locked") {
|
||||||
|
autoCheckStage = 2;
|
||||||
|
showWindow("unlock");
|
||||||
|
} else if ((status.slots[0].state == "present" ||
|
||||||
|
status.slots[1].state == "present") &&
|
||||||
|
(status.primaryGwSlot == 0 ||
|
||||||
|
status.mmState == "disabled")) {
|
||||||
|
runAsyncCmd(
|
||||||
|
"doas -n /usr/libexec/msm-modem-uim-selection boot >/dev/null "
|
||||||
|
"2>&1");
|
||||||
|
}
|
||||||
|
} else if (timeoutMs < 0 || aRem < timeoutMs) {
|
||||||
|
timeoutMs = static_cast<int>(aRem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pollfd pfds[2];
|
struct pollfd pfds[2];
|
||||||
|
|||||||
@@ -183,7 +183,14 @@ inline bool sendPluginCommand(const char* name, const std::string& cmdLine) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::string fifoPath = getPluginFifoPath(name);
|
std::string fifoPath = getPluginFifoPath(name);
|
||||||
int fd = ::open(fifoPath.c_str(), O_WRONLY | O_NONBLOCK | O_CLOEXEC);
|
int fd = -1;
|
||||||
|
for (int attempt = 0; attempt < 6; ++attempt) {
|
||||||
|
fd = ::open(fifoPath.c_str(), O_WRONLY | O_NONBLOCK | O_CLOEXEC);
|
||||||
|
if (fd >= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
::usleep(25000);
|
||||||
|
}
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1651,20 +1658,12 @@ inline std::string sendModemUssd(const std::string& input,
|
|||||||
if (clean.empty()) return "Empty USSD request.";
|
if (clean.empty()) return "Empty USSD request.";
|
||||||
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
std::string cmd;
|
std::string mode = (isReply && !isUssdCode(clean)) ? "respond" : "initiate";
|
||||||
if (isReply && !isUssdCode(clean)) {
|
std::string cmd =
|
||||||
cmd = "mmcli -m any --3gpp-ussd-respond=" + shellQuote(clean) + " 2>&1";
|
"doas -n /usr/libexec/msm-modem-uim-selection ussd " + mode + " " +
|
||||||
} else {
|
shellQuote(clean) + " 2>&1";
|
||||||
cmd = "mmcli -m any --3gpp-ussd-cancel >/dev/null 2>&1; "
|
|
||||||
"mmcli -m any --3gpp-ussd-initiate=" + shellQuote(clean) + " 2>&1";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string out = trimStr(runCaptureCmd(cmd, &rc));
|
std::string out = trimStr(runCaptureCmd(cmd, &rc));
|
||||||
size_t q1 = out.find('\'');
|
|
||||||
size_t q2 = out.rfind('\'');
|
|
||||||
if (q1 != std::string::npos && q2 != std::string::npos && q2 > q1) {
|
|
||||||
out = out.substr(q1 + 1, q2 - q1 - 1);
|
|
||||||
}
|
|
||||||
if (out.empty()) {
|
if (out.empty()) {
|
||||||
out = (rc == 0) ? "USSD request completed." : "USSD request failed.";
|
out = (rc == 0) ? "USSD request completed." : "USSD request failed.";
|
||||||
}
|
}
|
||||||
@@ -1698,7 +1697,9 @@ inline std::string sendModemUssd(const std::string& input,
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void cancelModemUssd() {
|
inline void cancelModemUssd() {
|
||||||
runAsyncCmd("mmcli -m any --3gpp-ussd-cancel >/dev/null 2>&1");
|
runAsyncCmd(
|
||||||
|
"doas -n /usr/libexec/msm-modem-uim-selection ussd cancel >/dev/null 2>&1 "
|
||||||
|
"|| mmcli -m any --3gpp-ussd-cancel >/dev/null 2>&1");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace bananarchy
|
} // namespace bananarchy
|
||||||
|
|||||||
+107
-24
@@ -816,6 +816,97 @@ write_str_file(const char *path, const char *val)
|
|||||||
return n > 0;
|
return n > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
dunst_window_visible(void)
|
||||||
|
{
|
||||||
|
if (!dpy)
|
||||||
|
return 0;
|
||||||
|
Window r_ret, p_ret, *children = NULL;
|
||||||
|
unsigned int nchildren = 0;
|
||||||
|
int found = 0;
|
||||||
|
if (!XQueryTree(dpy, root, &r_ret, &p_ret, &children, &nchildren) || !children)
|
||||||
|
return 0;
|
||||||
|
for (unsigned int i = 0; i < nchildren; i++) {
|
||||||
|
XWindowAttributes wa;
|
||||||
|
if (!XGetWindowAttributes(dpy, children[i], &wa) || wa.map_state != IsViewable)
|
||||||
|
continue;
|
||||||
|
XClassHint ch = { NULL, NULL };
|
||||||
|
if (XGetClassHint(dpy, children[i], &ch)) {
|
||||||
|
if ((ch.res_class && strcasecmp(ch.res_class, "Dunst") == 0) ||
|
||||||
|
(ch.res_name && strcasecmp(ch.res_name, "dunst") == 0))
|
||||||
|
found = 1;
|
||||||
|
if (ch.res_name)
|
||||||
|
XFree(ch.res_name);
|
||||||
|
if (ch.res_class)
|
||||||
|
XFree(ch.res_class);
|
||||||
|
if (found)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XFree(children);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
unmap_dunst_windows(void)
|
||||||
|
{
|
||||||
|
if (!dpy)
|
||||||
|
return;
|
||||||
|
Window r_ret, p_ret, *children = NULL;
|
||||||
|
unsigned int nchildren = 0;
|
||||||
|
int unmapped = 0;
|
||||||
|
if (!XQueryTree(dpy, root, &r_ret, &p_ret, &children, &nchildren) || !children)
|
||||||
|
return;
|
||||||
|
for (unsigned int i = 0; i < nchildren; i++) {
|
||||||
|
XClassHint ch = { NULL, NULL };
|
||||||
|
if (XGetClassHint(dpy, children[i], &ch)) {
|
||||||
|
if ((ch.res_class && strcasecmp(ch.res_class, "Dunst") == 0) ||
|
||||||
|
(ch.res_name && strcasecmp(ch.res_name, "dunst") == 0)) {
|
||||||
|
XUnmapWindow(dpy, children[i]);
|
||||||
|
unmapped = 1;
|
||||||
|
}
|
||||||
|
if (ch.res_name)
|
||||||
|
XFree(ch.res_name);
|
||||||
|
if (ch.res_class)
|
||||||
|
XFree(ch.res_class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XFree(children);
|
||||||
|
if (unmapped)
|
||||||
|
XFlush(dpy);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clear_all_notifications_now(void)
|
||||||
|
{
|
||||||
|
const char *ndir = getenv("SXMO_NOTIFDIR");
|
||||||
|
char default_dir[256];
|
||||||
|
if (!ndir || !ndir[0]) {
|
||||||
|
const char *home = getenv("HOME");
|
||||||
|
snprintf(default_dir, sizeof(default_dir), "%s/.local/share/sxmo/notifications",
|
||||||
|
(home && home[0]) ? home : "/home/user");
|
||||||
|
ndir = default_dir;
|
||||||
|
}
|
||||||
|
DIR *d = opendir(ndir);
|
||||||
|
if (d) {
|
||||||
|
struct dirent *ent;
|
||||||
|
while ((ent = readdir(d)) != NULL) {
|
||||||
|
if (ent->d_name[0] == '.')
|
||||||
|
continue;
|
||||||
|
char fpath[512];
|
||||||
|
snprintf(fpath, sizeof(fpath), "%s/%s", ndir, ent->d_name);
|
||||||
|
unlink(fpath);
|
||||||
|
}
|
||||||
|
closedir(d);
|
||||||
|
}
|
||||||
|
unmap_dunst_windows();
|
||||||
|
spawn_detached_sh(
|
||||||
|
"dunstctl close-all >/dev/null 2>&1; "
|
||||||
|
"dunstctl history-clear >/dev/null 2>&1; "
|
||||||
|
"pkill -x dunstify >/dev/null 2>&1; "
|
||||||
|
"sxmo_hook_statusbar.sh notifications >/dev/null 2>&1");
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_builtin_toggle(const char *toggle_name)
|
handle_builtin_toggle(const char *toggle_name)
|
||||||
{
|
{
|
||||||
@@ -914,27 +1005,7 @@ handle_builtin_toggle(const char *toggle_name)
|
|||||||
}
|
}
|
||||||
spawn_detached_sh("sxmo_hook_statusbar.sh audio");
|
spawn_detached_sh("sxmo_hook_statusbar.sh audio");
|
||||||
} else if (strcmp(toggle_name, "notif_clear_all") == 0) {
|
} else if (strcmp(toggle_name, "notif_clear_all") == 0) {
|
||||||
const char *ndir = getenv("SXMO_NOTIFDIR");
|
clear_all_notifications_now();
|
||||||
char default_dir[256];
|
|
||||||
if (!ndir || !ndir[0]) {
|
|
||||||
const char *home = getenv("HOME");
|
|
||||||
snprintf(default_dir, sizeof(default_dir), "%s/.local/share/sxmo/notifications",
|
|
||||||
(home && home[0]) ? home : "/home/user");
|
|
||||||
ndir = default_dir;
|
|
||||||
}
|
|
||||||
DIR *d = opendir(ndir);
|
|
||||||
if (d) {
|
|
||||||
struct dirent *ent;
|
|
||||||
while ((ent = readdir(d)) != NULL) {
|
|
||||||
if (ent->d_name[0] == '.')
|
|
||||||
continue;
|
|
||||||
char fpath[512];
|
|
||||||
snprintf(fpath, sizeof(fpath), "%s/%s", ndir, ent->d_name);
|
|
||||||
unlink(fpath);
|
|
||||||
}
|
|
||||||
closedir(d);
|
|
||||||
}
|
|
||||||
spawn_detached_sh("sxmo_hook_statusbar.sh notifs");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1031,7 +1102,10 @@ activate_selection(unsigned int ev_state)
|
|||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
unlink(fpath);
|
unlink(fpath);
|
||||||
spawn_detached_sh("sxmo_hook_statusbar.sh notifs");
|
unmap_dunst_windows();
|
||||||
|
spawn_detached_sh(
|
||||||
|
"dunstctl close-all >/dev/null 2>&1; "
|
||||||
|
"sxmo_hook_statusbar.sh notifications >/dev/null 2>&1");
|
||||||
hide_menu();
|
hide_menu();
|
||||||
menu_mode = MODE_NONE;
|
menu_mode = MODE_NONE;
|
||||||
if (action_cmd[0] && strcmp(action_cmd, "none") != 0)
|
if (action_cmd[0] && strcmp(action_cmd, "none") != 0)
|
||||||
@@ -1040,6 +1114,11 @@ activate_selection(unsigned int ev_state)
|
|||||||
}
|
}
|
||||||
if (strncmp(act, "@toggle:", 8) == 0) {
|
if (strncmp(act, "@toggle:", 8) == 0) {
|
||||||
handle_builtin_toggle(act + 8);
|
handle_builtin_toggle(act + 8);
|
||||||
|
if (strcmp(act + 8, "notif_clear_all") == 0) {
|
||||||
|
hide_menu();
|
||||||
|
menu_mode = MODE_NONE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
char cur_menu[64];
|
char cur_menu[64];
|
||||||
snprintf(cur_menu, sizeof(cur_menu), "%s", current_builtin_menu);
|
snprintf(cur_menu, sizeof(cur_menu), "%s", current_builtin_menu);
|
||||||
open_builtin_menu(cur_menu, cur_idx);
|
open_builtin_menu(cur_menu, cur_idx);
|
||||||
@@ -1906,9 +1985,13 @@ open_builtin_menu(const char *menu_name, int keep_idx)
|
|||||||
reset_session_defaults(1, "Sys");
|
reset_session_defaults(1, "Sys");
|
||||||
append_active_call_entries();
|
append_active_call_entries();
|
||||||
int nnotifs = count_notifications();
|
int nnotifs = count_notifications();
|
||||||
|
int dunst_vis = dunst_window_visible();
|
||||||
if (nnotifs > 0) {
|
if (nnotifs > 0) {
|
||||||
snprintf(label, sizeof(label), "%s Notifications (%d)", ICON_BEL, nnotifs);
|
snprintf(label, sizeof(label), "%s Notifications (%d)", ICON_BEL, nnotifs);
|
||||||
add_menu_item(label, "@menu:notifications", 1);
|
add_menu_item(label, "@menu:notifications", 1);
|
||||||
|
} else if (dunst_vis) {
|
||||||
|
snprintf(label, sizeof(label), "%s Clear Notification", ICON_BEL);
|
||||||
|
add_menu_item(label, "@toggle:notif_clear_all", 0);
|
||||||
}
|
}
|
||||||
const char *sh = getenv("SHELL");
|
const char *sh = getenv("SHELL");
|
||||||
if (!sh || !sh[0])
|
if (!sh || !sh[0])
|
||||||
@@ -2105,9 +2188,9 @@ open_builtin_menu(const char *menu_name, int keep_idx)
|
|||||||
add_menu_item(label, "@close", 0);
|
add_menu_item(label, "@close", 0);
|
||||||
} else if (strcmp(menu_name, "notifications") == 0) {
|
} else if (strcmp(menu_name, "notifications") == 0) {
|
||||||
reset_session_defaults(1, "Notifs");
|
reset_session_defaults(1, "Notifs");
|
||||||
populate_notifications_menu();
|
|
||||||
snprintf(label, sizeof(label), "%s Clear All Notifications", ICON_CLS);
|
snprintf(label, sizeof(label), "%s Clear All Notifications", ICON_CLS);
|
||||||
add_menu_item(label, "@toggle:notif_clear_all", 1);
|
add_menu_item(label, "@toggle:notif_clear_all", 0);
|
||||||
|
populate_notifications_menu();
|
||||||
snprintf(label, sizeof(label), "%s System Menu", ICON_MNU);
|
snprintf(label, sizeof(label), "%s System Menu", ICON_MNU);
|
||||||
add_menu_item(label, "@menu:sys", 1);
|
add_menu_item(label, "@menu:sys", 1);
|
||||||
snprintf(label, sizeof(label), "%s Close Menu", ICON_CLS);
|
snprintf(label, sizeof(label), "%s Close Menu", ICON_CLS);
|
||||||
|
|||||||
Reference in New Issue
Block a user