Add modem/networks DWM plugins, Dual-SIM & PIN/PUK support, built-in dmenu views, and game UX fixes
This commit is contained in:
+415
@@ -0,0 +1,415 @@
|
||||
#!/bin/sh
|
||||
# Bananarchy Dual-SIM & QMI UIM Provisioning Helper for Qualcomm MSM8905/MSM8909
|
||||
set -eu
|
||||
|
||||
CONF_FILE="/etc/conf.d/msm-modem-uim-selection"
|
||||
if [ -r "$CONF_FILE" ]; then
|
||||
# shellcheck disable=SC1090
|
||||
. "$CONF_FILE"
|
||||
fi
|
||||
|
||||
SIM_WAIT_TIME="${SIM_WAIT_TIME:-${sim_wait_time:-4}}"
|
||||
PREFERRED_SIM_SLOT="${PREFERRED_SIM_SLOT:-${preferred_sim_slot:-1}}"
|
||||
QMICLI_MODEM=""
|
||||
|
||||
detect_qmicli_modem() {
|
||||
if ! command -v qmicli >/dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
if [ -e "/dev/modem" ]; 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"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
wait_for_qmicli_modem() {
|
||||
max_wait="${1:-45}"
|
||||
count=0
|
||||
while [ "$count" -lt "$max_wait" ]; do
|
||||
if detect_qmicli_modem; then
|
||||
return 0
|
||||
fi
|
||||
sleep 1
|
||||
count=$((count + 1))
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# Parse `qmicli --uim-get-card-status` into shell-safe KEY=VALUE lines
|
||||
parse_uim_card_status() {
|
||||
raw_status="$1"
|
||||
pref_slot="$2"
|
||||
printf "%s\n" "$raw_status" | awk -v pref="$pref_slot" '
|
||||
BEGIN {
|
||||
prim_slot = 0
|
||||
prim_app = 0
|
||||
cur_slot = 0
|
||||
in_app = 0
|
||||
for (s = 1; s <= 2; s++) {
|
||||
cstate[s] = "absent"
|
||||
rawstate[s] = "absent"
|
||||
upin_state[s] = "not-initialized"
|
||||
upin_ret[s] = 0
|
||||
upuk_ret[s] = 0
|
||||
app_type[s] = "none"
|
||||
app_state[s] = "none"
|
||||
aid[s] = ""
|
||||
pin1_state[s] = "not-initialized"
|
||||
pin1_ret[s] = 0
|
||||
puk1_ret[s] = 0
|
||||
}
|
||||
}
|
||||
/Primary GW:/ {
|
||||
if ($0 ~ /slot \x27[0-9]+\x27/) {
|
||||
line = $0
|
||||
sub(/.*slot \x27/, "", line)
|
||||
sub(/\x27.*/, "", line)
|
||||
prim_slot = line + 0
|
||||
}
|
||||
if ($0 ~ /application \x27[0-9]+\x27/) {
|
||||
line = $0
|
||||
sub(/.*application \x27/, "", line)
|
||||
sub(/\x27.*/, "", line)
|
||||
prim_app = line + 0
|
||||
}
|
||||
}
|
||||
/^[[:space:]]*Slot \[[0-9]+\]:/ {
|
||||
line = $0
|
||||
sub(/.*Slot \[/, "", line)
|
||||
sub(/\].*/, "", line)
|
||||
cur_slot = line + 0
|
||||
in_app = 0
|
||||
next
|
||||
}
|
||||
cur_slot >= 1 && cur_slot <= 2 {
|
||||
if ($0 ~ /^[[:space:]]*Application \[[0-9]+\]:/) {
|
||||
in_app = 1
|
||||
next
|
||||
}
|
||||
if (!in_app && $0 ~ /Card state:/) {
|
||||
line = $0
|
||||
sub(/.*Card state: \x27/, "", line)
|
||||
sub(/\x27.*/, "", line)
|
||||
rawstate[cur_slot] = line
|
||||
if (line == "present") cstate[cur_slot] = "present"
|
||||
else if (line == "absent" || line ~ /no-atr-received/) cstate[cur_slot] = "absent"
|
||||
else cstate[cur_slot] = "error"
|
||||
}
|
||||
if (!in_app && $0 ~ /UPIN state:/) {
|
||||
line = $0
|
||||
sub(/.*UPIN state: \x27/, "", line)
|
||||
sub(/\x27.*/, "", line)
|
||||
upin_state[cur_slot] = line
|
||||
}
|
||||
if (!in_app && $0 ~ /UPIN retries:/) {
|
||||
line = $0
|
||||
sub(/.*UPIN retries: \x27/, "", line)
|
||||
sub(/\x27.*/, "", line)
|
||||
upin_ret[cur_slot] = line + 0
|
||||
}
|
||||
if (!in_app && $0 ~ /UPUK retries:/) {
|
||||
line = $0
|
||||
sub(/.*UPUK retries: \x27/, "", line)
|
||||
sub(/\x27.*/, "", line)
|
||||
upuk_ret[cur_slot] = line + 0
|
||||
}
|
||||
if (in_app && $0 ~ /Application type:/) {
|
||||
line = $0
|
||||
sub(/.*Application type: \x27/, "", line)
|
||||
sub(/\x27.*/, "", line)
|
||||
if (line ~ /^usim/) {
|
||||
app_type[cur_slot] = "usim"
|
||||
want_aid[cur_slot] = 2
|
||||
} else if (line ~ /^sim/ && app_type[cur_slot] != "usim") {
|
||||
app_type[cur_slot] = "sim"
|
||||
want_aid[cur_slot] = 1
|
||||
} else {
|
||||
want_aid[cur_slot] = 0
|
||||
}
|
||||
}
|
||||
if (in_app && $0 ~ /Application state:/ && want_aid[cur_slot] > 0) {
|
||||
line = $0
|
||||
sub(/.*Application state: \x27/, "", line)
|
||||
sub(/\x27.*/, "", line)
|
||||
app_state[cur_slot] = line
|
||||
}
|
||||
if (in_app && $0 ~ /Application ID:/ && want_aid[cur_slot] > 0) {
|
||||
need_aid_line[cur_slot] = 1
|
||||
next
|
||||
}
|
||||
if (in_app && need_aid_line[cur_slot] == 1) {
|
||||
line = $0
|
||||
gsub(/^[[:space:]]+|[[:space:]]+$/, "", line)
|
||||
if (line != "") {
|
||||
aid[cur_slot] = line
|
||||
}
|
||||
need_aid_line[cur_slot] = 0
|
||||
}
|
||||
if (in_app && $0 ~ /PIN1 state:/ && want_aid[cur_slot] > 0) {
|
||||
line = $0
|
||||
sub(/.*PIN1 state: \x27/, "", line)
|
||||
sub(/\x27.*/, "", line)
|
||||
pin1_state[cur_slot] = line
|
||||
}
|
||||
if (in_app && $0 ~ /PIN1 retries:/ && want_aid[cur_slot] > 0) {
|
||||
line = $0
|
||||
sub(/.*PIN1 retries: \x27/, "", line)
|
||||
sub(/\x27.*/, "", line)
|
||||
pin1_ret[cur_slot] = line + 0
|
||||
}
|
||||
if (in_app && $0 ~ /PUK1 retries:/ && want_aid[cur_slot] > 0) {
|
||||
line = $0
|
||||
sub(/.*PUK1 retries: \x27/, "", line)
|
||||
sub(/\x27.*/, "", line)
|
||||
puk1_ret[cur_slot] = line + 0
|
||||
}
|
||||
}
|
||||
END {
|
||||
printf "PREFERRED_SLOT=%d\n", (pref == 2 ? 2 : 1)
|
||||
printf "PRIMARY_GW_SLOT=%d\n", prim_slot
|
||||
printf "PRIMARY_GW_APP=%d\n", prim_app
|
||||
for (s = 1; s <= 2; s++) {
|
||||
printf "SLOT%d_STATE=%s\n", s, cstate[s]
|
||||
printf "SLOT%d_RAW_STATE=%s\n", s, rawstate[s]
|
||||
printf "SLOT%d_APP_TYPE=%s\n", s, app_type[s]
|
||||
printf "SLOT%d_APP_STATE=%s\n", s, app_state[s]
|
||||
printf "SLOT%d_AID=%s\n", s, aid[s]
|
||||
printf "SLOT%d_PIN1_STATE=%s\n", s, pin1_state[s]
|
||||
printf "SLOT%d_PIN1_RETRIES=%d\n", s, pin1_ret[s]
|
||||
printf "SLOT%d_PUK1_RETRIES=%d\n", s, puk1_ret[s]
|
||||
printf "SLOT%d_UPIN_STATE=%s\n", s, upin_state[s]
|
||||
printf "SLOT%d_UPIN_RETRIES=%d\n", s, upin_ret[s]
|
||||
printf "SLOT%d_UPUK_RETRIES=%d\n", s, upuk_ret[s]
|
||||
}
|
||||
}
|
||||
'
|
||||
}
|
||||
|
||||
save_preferred_slot() {
|
||||
target_slot="$1"
|
||||
if [ -f "$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"
|
||||
else
|
||||
printf "\npreferred_sim_slot=%s\n" "$target_slot" >> "$CONF_FILE"
|
||||
fi
|
||||
else
|
||||
printf "sim_wait_time=4\npreferred_sim_slot=%s\n" "$target_slot" > "$CONF_FILE"
|
||||
fi
|
||||
}
|
||||
|
||||
provision_slot() {
|
||||
req_slot="$1"
|
||||
wait_secs="$2"
|
||||
|
||||
if ! wait_for_qmicli_modem "$wait_secs"; then
|
||||
echo "No modem available." >&2
|
||||
return 2
|
||||
fi
|
||||
|
||||
QMI_CARDS="$($QMICLI_MODEM --uim-get-card-status 2>/dev/null || true)"
|
||||
count=0
|
||||
while ! printf "%s" "$QMI_CARDS" | grep -Fq "Card state: 'present'"; do
|
||||
if [ "$count" -ge "$SIM_WAIT_TIME" ]; then
|
||||
echo "No SIM detected after $SIM_WAIT_TIME seconds."
|
||||
return 0
|
||||
fi
|
||||
sleep 1
|
||||
count=$((count + 1))
|
||||
QMI_CARDS="$($QMICLI_MODEM --uim-get-card-status 2>/dev/null || true)"
|
||||
done
|
||||
|
||||
eval "$(parse_uim_card_status "$QMI_CARDS" "$req_slot")"
|
||||
|
||||
chosen_slot=""
|
||||
chosen_aid=""
|
||||
if [ "$req_slot" = "2" ]; then
|
||||
if [ "$SLOT2_STATE" = "present" ] && [ -n "$SLOT2_AID" ]; then
|
||||
chosen_slot="2"
|
||||
chosen_aid="$SLOT2_AID"
|
||||
elif [ "$SLOT1_STATE" = "present" ] && [ -n "$SLOT1_AID" ]; then
|
||||
chosen_slot="1"
|
||||
chosen_aid="$SLOT1_AID"
|
||||
fi
|
||||
else
|
||||
if [ "$SLOT1_STATE" = "present" ] && [ -n "$SLOT1_AID" ]; then
|
||||
chosen_slot="1"
|
||||
chosen_aid="$SLOT1_AID"
|
||||
elif [ "$SLOT2_STATE" = "present" ] && [ -n "$SLOT2_AID" ]; then
|
||||
chosen_slot="2"
|
||||
chosen_aid="$SLOT2_AID"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$chosen_slot" ] || [ -z "$chosen_aid" ]; then
|
||||
echo "No valid USIM/SIM application found on any slot."
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ "$PRIMARY_GW_SLOT" != "0" ]; then
|
||||
$QMICLI_MODEM --uim-change-provisioning-session='activate=no,session-type=primary-gw-provisioning' >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
echo "Selecting AID $chosen_aid on slot $chosen_slot"
|
||||
$QMICLI_MODEM --uim-change-provisioning-session="slot=$chosen_slot,activate=yes,session-type=primary-gw-provisioning,aid=$chosen_aid" >/dev/null
|
||||
return $?
|
||||
}
|
||||
|
||||
cmd="${1:-boot}"
|
||||
|
||||
case "$cmd" in
|
||||
boot)
|
||||
if command -v systemd-notify >/dev/null 2>&1; then
|
||||
trap '[ $? -eq 0 ] && systemd-notify --ready' EXIT
|
||||
fi
|
||||
case "$(cat /sys/devices/soc0/machine 2>/dev/null || true)" in
|
||||
APQ*)
|
||||
echo "Skipping SIM configuration on APQ SoC."
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
provision_slot "$PREFERRED_SIM_SLOT" 45
|
||||
exit $?
|
||||
;;
|
||||
|
||||
status)
|
||||
if ! detect_qmicli_modem; then
|
||||
echo "MODEM_AVAILABLE=0"
|
||||
echo "PREFERRED_SLOT=$PREFERRED_SIM_SLOT"
|
||||
exit 0
|
||||
fi
|
||||
QMI_CARDS="$($QMICLI_MODEM --uim-get-card-status 2>/dev/null || true)"
|
||||
if [ -z "$QMI_CARDS" ]; then
|
||||
echo "MODEM_AVAILABLE=0"
|
||||
echo "PREFERRED_SLOT=$PREFERRED_SIM_SLOT"
|
||||
exit 0
|
||||
fi
|
||||
echo "MODEM_AVAILABLE=1"
|
||||
parse_uim_card_status "$QMI_CARDS" "$PREFERRED_SIM_SLOT"
|
||||
exit 0
|
||||
;;
|
||||
|
||||
switch)
|
||||
target="${2:-1}"
|
||||
if [ "$target" != "1" ] && [ "$target" != "2" ]; then
|
||||
echo "Invalid slot: $target (must be 1 or 2)" >&2
|
||||
exit 1
|
||||
fi
|
||||
save_preferred_slot "$target"
|
||||
SIM_WAIT_TIME=2
|
||||
provision_slot "$target" 5
|
||||
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
|
||||
exit 0
|
||||
;;
|
||||
|
||||
verify-pin)
|
||||
slot="${2:-1}"
|
||||
pin="${3:-}"
|
||||
if [ -z "$pin" ]; then
|
||||
echo "Missing PIN" >&2
|
||||
exit 1
|
||||
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" --pin="$pin" >/dev/null 2>&1; then
|
||||
exit 0
|
||||
fi
|
||||
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
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
exit 1
|
||||
;;
|
||||
|
||||
unblock-puk)
|
||||
slot="${2:-1}"
|
||||
puk="${3:-}"
|
||||
newpin="${4:-}"
|
||||
if [ -z "$puk" ] || [ -z "$newpin" ]; then
|
||||
echo "Missing PUK or new PIN" >&2
|
||||
exit 1
|
||||
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" --puk="$puk" --pin="$newpin" >/dev/null 2>&1; then
|
||||
exit 0
|
||||
fi
|
||||
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
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
exit 1
|
||||
;;
|
||||
|
||||
set-pin-lock)
|
||||
slot="${2:-1}"
|
||||
mode="${3:-enable}"
|
||||
pin="${4:-}"
|
||||
if [ -z "$pin" ] || { [ "$mode" != "enable" ] && [ "$mode" != "disable" ]; }; then
|
||||
echo "Usage: $0 set-pin-lock <1|2> <enable|disable> <pin>" >&2
|
||||
exit 1
|
||||
fi
|
||||
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 [ "$mode" = "enable" ] && mmcli -i "$sim_id" --enable-pin --pin="$pin" >/dev/null 2>&1; then
|
||||
exit 0
|
||||
elif [ "$mode" = "disable" ] && mmcli -i "$sim_id" --disable-pin --pin="$pin" >/dev/null 2>&1; then
|
||||
exit 0
|
||||
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
|
||||
;;
|
||||
|
||||
change-pin)
|
||||
slot="${2:-1}"
|
||||
oldpin="${3:-}"
|
||||
newpin="${4:-}"
|
||||
if [ -z "$oldpin" ] || [ -z "$newpin" ]; then
|
||||
echo "Usage: $0 change-pin <1|2> <oldpin> <newpin>" >&2
|
||||
exit 1
|
||||
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 $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
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
exit 1
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Usage: $0 [boot|status|switch <1|2>|verify-pin <slot> <pin>|unblock-puk <slot> <puk> <newpin>|set-pin-lock <slot> <enable|disable> <pin>|change-pin <slot> <oldpin> <newpin>]" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user