Fix OpenRC boot hang in msm-modem-uim-selection, USB gadget UDC race/unbind, and SIM2 lock sync

This commit is contained in:
Luxferre
2026-10-25 12:32:46 +02:00
parent 33d3d225c1
commit b7c57aab2f
11 changed files with 1733 additions and 58 deletions
@@ -8,31 +8,80 @@ if [ -r "$CONF_FILE" ]; then
. "$CONF_FILE"
fi
SIM_WAIT_TIME="${SIM_WAIT_TIME:-${sim_wait_time:-10}}"
SIM_WAIT_TIME="${SIM_WAIT_TIME:-${sim_wait_time:-4}}"
PREFERRED_SIM_SLOT="${PREFERRED_SIM_SLOT:-${preferred_sim_slot:-1}}"
QMICLI_MODEM=""
ensure_usb_network_gadget() {
CONFIGFS="/sys/kernel/config/usb_gadget"
if ! [ -d "$CONFIGFS" ]; then
modprobe libcomposite 2>/dev/null || true
mount -t configfs configfs /sys/kernel/config 2>/dev/null || true
fi
udc_dev="$(ls /sys/class/udc 2>/dev/null | head -n 1 || true)"
if [ -z "$udc_dev" ]; then
modprobe pm8916-lbc 2>/dev/null || true
w=0
while [ -z "$udc_dev" ] && [ "$w" -lt 20 ]; do
sleep 0.1
udc_dev="$(ls /sys/class/udc 2>/dev/null | head -n 1 || true)"
w=$((w + 1))
done
fi
if [ -d "$CONFIGFS" ] && [ -n "$udc_dev" ]; then
if ! [ -d "$CONFIGFS/g1" ]; then
mkdir -p "$CONFIGFS/g1" 2>/dev/null || true
echo "0x18D1" > "$CONFIGFS/g1/idVendor" 2>/dev/null || true
echo "0xD001" > "$CONFIGFS/g1/idProduct" 2>/dev/null || true
mkdir -p "$CONFIGFS/g1/strings/0x409" 2>/dev/null || true
echo "Nokia" > "$CONFIGFS/g1/strings/0x409/manufacturer" 2>/dev/null || true
echo "Bananarchy" > "$CONFIGFS/g1/strings/0x409/serialnumber" 2>/dev/null || true
echo "Nokia 8110 4G" > "$CONFIGFS/g1/strings/0x409/product" 2>/dev/null || true
func="ncm.usb0"
if ! mkdir -p "$CONFIGFS/g1/functions/$func" 2>/dev/null; then
func="rndis.usb0"
mkdir -p "$CONFIGFS/g1/functions/$func" 2>/dev/null || true
fi
mkdir -p "$CONFIGFS/g1/configs/c.1/strings/0x409" 2>/dev/null || true
echo "USB network" > "$CONFIGFS/g1/configs/c.1/strings/0x409/configuration" 2>/dev/null || true
ln -sf "$CONFIGFS/g1/functions/$func" "$CONFIGFS/g1/configs/c.1/" 2>/dev/null || true
fi
cur_udc="$(cat "$CONFIGFS/g1/UDC" 2>/dev/null | tr -d '[:space:]' || true)"
if [ -z "$cur_udc" ]; then
echo "$udc_dev" > "$CONFIGFS/g1/UDC" 2>/dev/null || true
fi
fi
if ip link show dev usb0 >/dev/null 2>&1; then
ip link set usb0 up 2>/dev/null || true
ip -4 addr show dev usb0 2>/dev/null | grep -q "172.16.42.1" || \
ip addr add 172.16.42.1/16 dev usb0 2>/dev/null || true
if ! pidof unudhcpd >/dev/null 2>&1; then
(unudhcpd -i usb0 -s 172.16.42.1 -c 172.16.42.2 >/dev/null 2>&1) &
fi
fi
}
detect_qmicli_modem() {
if ! command -v qmicli >/dev/null 2>&1; then
return 1
fi
if qmicli --silent -pd qrtr://0 --uim-noop >/dev/null 2>&1; then
QMICLI_MODEM="qmicli --silent -pd qrtr://0"
if timeout 3 qmicli --silent -pd qrtr://0 --uim-noop >/dev/null 2>&1; then
QMICLI_MODEM="timeout 4 qmicli --silent -pd qrtr://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"
if timeout 3 qmicli --silent -pd /dev/wwan0qmi0 --device-open-qmi --uim-noop >/dev/null 2>&1; then
QMICLI_MODEM="timeout 4 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"
elif timeout 3 qmicli --silent -d /dev/wwan0qmi0 --device-open-qmi --uim-noop >/dev/null 2>&1; then
QMICLI_MODEM="timeout 4 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"
if timeout 3 qmicli --silent -pd /dev/modem --uim-noop >/dev/null 2>&1; then
QMICLI_MODEM="timeout 4 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"
elif timeout 3 qmicli --silent -d /dev/modem --uim-noop >/dev/null 2>&1; then
QMICLI_MODEM="timeout 4 qmicli --silent -d /dev/modem"
return 0
fi
fi
@@ -40,7 +89,7 @@ detect_qmicli_modem() {
}
wait_for_qmicli_modem() {
max_wait="${1:-45}"
max_wait="${1:-12}"
count=0
while [ "$count" -lt "$max_wait" ]; do
if detect_qmicli_modem; then
@@ -337,8 +386,6 @@ provision_slot() {
return 2
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)"
count=0
while : ; do
@@ -459,8 +506,8 @@ enable_and_register_modem() {
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)"
while [ "$i" -lt 10 ]; do
mm_state="$(timeout 3 mmcli -m any -K 2>/dev/null | awk -F': ' '/^modem\.generic\.state / {print $2; exit}' || true)"
if [ -n "$mm_state" ]; then
break
fi
@@ -470,14 +517,14 @@ enable_and_register_modem() {
if [ "$mm_state" = "failed" ] || { [ "$force_unlock" = "1" ] && [ "$mm_state" = "locked" ]; }; then
if command -v rc-service >/dev/null 2>&1; then
rc-service modemmanager restart >/dev/null 2>&1 || true
timeout 6 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
timeout 6 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)"
while [ "$i" -lt 10 ]; do
mm_state="$(timeout 3 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
@@ -491,14 +538,14 @@ enable_and_register_modem() {
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)"
while [ "$i" -lt 8 ]; do
mm_state="$(timeout 3 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
timeout 4 mmcli -m any -e >/dev/null 2>&1 || true
;;
enabled)
mmcli -m any --3gpp-register-home >/dev/null 2>&1 || true
timeout 4 mmcli -m any --3gpp-register-home >/dev/null 2>&1 || true
break
;;
searching|registered|connected|connecting)
@@ -512,16 +559,26 @@ enable_and_register_modem() {
i=$((i + 1))
done
mmcli -m any --3gpp-register-home >/dev/null 2>&1 || true
timeout 4 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
DISPLAY="${DISPLAY:-:0}" timeout 3 sxmo_hook_statusbar.sh modem >/dev/null 2>&1 || true
fi
}
spawn_enable_and_register() {
s_slot="${1:-$PREFERRED_SIM_SLOT}"
s_force="${2:-0}"
(
exec >/dev/null 2>&1 </dev/null 3>&- 4>&- 5>&- 6>&- 7>&- 8>&- 9>&- 2>/dev/null || true
enable_and_register_modem "$s_slot" "$s_force"
) &
}
cmd="${1:-boot}"
case "$cmd" in
boot)
ensure_usb_network_gadget
if command -v systemd-notify >/dev/null 2>&1; then
trap '[ $? -eq 0 ] && systemd-notify --ready' EXIT
fi
@@ -531,8 +588,7 @@ case "$cmd" in
exit 0
;;
esac
provision_slot "$PREFERRED_SIM_SLOT" 45
( enable_and_register_modem "$PREFERRED_SIM_SLOT" 0 ) >/dev/null 2>&1 </dev/null &
provision_slot "$PREFERRED_SIM_SLOT" 10 || true
exit 0
;;
@@ -567,11 +623,11 @@ case "$cmd" in
SIM_WAIT_TIME=3
provision_slot "$target" 5
if command -v rc-service >/dev/null 2>&1; then
rc-service modemmanager restart >/dev/null 2>&1 || true
timeout 6 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
timeout 6 systemctl restart ModemManager >/dev/null 2>&1 || true
fi
( enable_and_register_modem "$target" 0 ) >/dev/null 2>&1 </dev/null &
spawn_enable_and_register "$target" 0
exit 0
;;
@@ -584,8 +640,8 @@ case "$cmd" in
fi
prepare_slot_for_pin_op "$slot"
verified=0
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
sim_id="$(timeout 3 mmcli -m any 2>/dev/null | grep -oE 'SIM/[0-9]+' | head -n1 | cut -d'/' -f2 || true)"
if [ -n "$sim_id" ] && timeout 4 mmcli -i "$sim_id" --pin="$pin" >/dev/null 2>&1; then
verified=1
fi
if [ "$verified" = "0" ] && [ -n "$QMICLI_MODEM" ]; then
@@ -625,10 +681,10 @@ case "$cmd" in
SIM_WAIT_TIME=2
provision_slot "$slot" 3 >/dev/null 2>&1 || true
if [ -n "$sim_id" ]; then
mmcli -i "$sim_id" --pin="$pin" >/dev/null 2>&1 || true
timeout 4 mmcli -i "$sim_id" --pin="$pin" >/dev/null 2>&1 || true
fi
mmcli -m any -e >/dev/null 2>&1 || true
( enable_and_register_modem "$slot" 1 ) >/dev/null 2>&1 </dev/null &
timeout 4 mmcli -m any -e >/dev/null 2>&1 || true
spawn_enable_and_register "$slot" 1
exit 0
fi
exit 1
@@ -644,8 +700,8 @@ case "$cmd" in
fi
prepare_slot_for_pin_op "$slot"
unblocked=0
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
sim_id="$(timeout 3 mmcli -m any 2>/dev/null | grep -oE 'SIM/[0-9]+' | head -n1 | cut -d'/' -f2 || true)"
if [ -n "$sim_id" ] && timeout 4 mmcli -i "$sim_id" --puk="$puk" --pin="$newpin" >/dev/null 2>&1; then
unblocked=1
fi
if [ "$unblocked" = "0" ] && [ -n "$QMICLI_MODEM" ]; then
@@ -669,8 +725,8 @@ case "$cmd" in
save_preferred_slot "$slot"
SIM_WAIT_TIME=2
provision_slot "$slot" 3 >/dev/null 2>&1 || true
mmcli -m any -e >/dev/null 2>&1 || true
( enable_and_register_modem "$slot" 1 ) >/dev/null 2>&1 </dev/null &
timeout 4 mmcli -m any -e >/dev/null 2>&1 || true
spawn_enable_and_register "$slot" 1
exit 0
fi
exit 1
@@ -795,6 +851,7 @@ case "$cmd" in
mode="${2:-status}"
case "$mode" in
on)
ensure_usb_network_gadget
sysctl -w net.ipv4.ip_forward=1 >/dev/null 2>&1 || true
nft add table ip nat 2>/dev/null || true
nft 'add chain ip nat postrouting { type nat hook postrouting priority 100 ; }' 2>/dev/null || true
@@ -805,6 +862,7 @@ case "$cmd" in
echo "1" > /tmp/bananarchy_usb_tether.active
;;
off)
ensure_usb_network_gadget
sysctl -w net.ipv4.ip_forward=0 >/dev/null 2>&1 || true
nft delete table ip nat 2>/dev/null || true
nmcli connection delete USBNetworkShare >/dev/null 2>&1 || true