modem: bind QMI primary-gw-provisioning session before USIM PIN verification and fix SIM2 target slot resolution

This commit is contained in:
Luxferre
2026-10-25 11:50:57 +02:00
parent b56f310f21
commit 33d3d225c1
4 changed files with 142 additions and 54 deletions
Binary file not shown.
@@ -396,14 +396,14 @@ provision_slot() {
save_preferred_slot "$chosen_slot"
fi
# If already provisioned on the chosen slot and application is ready, keep session intact
# If already provisioned on the chosen slot and application is ready or waiting for PIN, 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."
if [ "$PRIMARY_GW_SLOT" = "$chosen_slot" ] && { [ "$chosen_app_state" = "ready" ] || [ "$chosen_app_state" = "pin1-or-upin-pin-required" ] || [ "$chosen_app_state" = "puk1-or-upin-puk-required" ]; }; then
echo "Slot $chosen_slot already bound to primary-gw-provisioning ($chosen_app_state)."
return 0
fi
if [ "$PRIMARY_GW_SLOT" != "0" ] && [ "$PRIMARY_GW_SLOT" != "$chosen_slot" ]; then
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
@@ -419,8 +419,39 @@ provision_slot() {
return 0
}
prepare_slot_for_pin_op() {
req_slot="${1:-1}"
slot="$req_slot"
target_aid=""
if detect_qmicli_modem; then
QMI_CARDS="$($QMICLI_MODEM --uim-get-card-status 2>/dev/null || true)"
if [ -n "$QMI_CARDS" ]; then
eval "$(parse_uim_card_status "$QMI_CARDS" "$PREFERRED_SIM_SLOT")"
if [ "$slot" = "1" ] && [ "$SLOT1_STATE" != "present" ] && [ "$SLOT2_STATE" = "present" ]; then
slot="2"
elif [ "$slot" = "2" ] && [ "$SLOT2_STATE" != "present" ] && [ "$SLOT1_STATE" = "present" ]; then
slot="1"
fi
eval "target_aid=\$SLOT${slot}_AID"
if [ "$PRIMARY_GW_SLOT" != "$slot" ]; then
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
if [ -n "$target_aid" ]; then
$QMICLI_MODEM --uim-change-provisioning-session="slot=$slot,activate=yes,session-type=primary-gw-provisioning,aid=$target_aid" >/dev/null 2>&1 || \
$QMICLI_MODEM --uim-change-provisioning-session="slot=$slot,activate=yes,session-type=primary-gw-provisioning" >/dev/null 2>&1 || true
else
$QMICLI_MODEM --uim-change-provisioning-session="slot=$slot,activate=yes,session-type=primary-gw-provisioning" >/dev/null 2>&1 || true
fi
sleep 0.6
fi
fi
fi
}
enable_and_register_modem() {
target_slot="${1:-$PREFERRED_SIM_SLOT}"
force_unlock="${2:-0}"
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
@@ -437,7 +468,7 @@ enable_and_register_modem() {
i=$((i + 1))
done
if [ "$mm_state" = "failed" ]; then
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
elif command -v systemctl >/dev/null 2>&1; then
@@ -501,7 +532,7 @@ case "$cmd" in
;;
esac
provision_slot "$PREFERRED_SIM_SLOT" 45
( enable_and_register_modem "$PREFERRED_SIM_SLOT" ) >/dev/null 2>&1 </dev/null &
( enable_and_register_modem "$PREFERRED_SIM_SLOT" 0 ) >/dev/null 2>&1 </dev/null &
exit 0
;;
@@ -540,7 +571,7 @@ case "$cmd" in
elif command -v systemctl >/dev/null 2>&1; then
systemctl restart ModemManager >/dev/null 2>&1 || true
fi
( enable_and_register_modem "$target" ) >/dev/null 2>&1 </dev/null &
( enable_and_register_modem "$target" 0 ) >/dev/null 2>&1 </dev/null &
exit 0
;;
@@ -551,25 +582,53 @@ case "$cmd" in
echo "Missing PIN" >&2
exit 1
fi
prepare_slot_for_pin_op "$slot"
verified=0
if detect_qmicli_modem; then
if $QMICLI_MODEM --uim-verify-pin="PIN1,$pin,session-type=card-slot-$slot" >/dev/null 2>&1; 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
if [ "$verified" = "0" ] && [ -n "$QMICLI_MODEM" ]; then
if $QMICLI_MODEM --uim-verify-pin="PIN1,$pin,session-type=primary-gw-provisioning" >/dev/null 2>&1; then
verified=1
elif $QMICLI_MODEM --uim-verify-pin="PIN1,$pin,session-type=primary-gw-provisioning" >/dev/null 2>&1; then
elif $QMICLI_MODEM --uim-verify-pin="PIN1,$pin,session-type=card-slot-$slot" >/dev/null 2>&1; then
verified=1
elif $QMICLI_MODEM --uim-verify-pin="PIN1,$pin" >/dev/null 2>&1; then
verified=1
elif $QMICLI_MODEM --uim-verify-pin="UPIN,$pin,session-type=primary-gw-provisioning" >/dev/null 2>&1; then
verified=1
elif $QMICLI_MODEM --uim-verify-pin="UPIN,$pin,session-type=card-slot-$slot" >/dev/null 2>&1; then
verified=1
elif $QMICLI_MODEM --dms-uim-verify-pin="PIN,$pin" >/dev/null 2>&1; then
verified=1
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
at_cpin="$("$0" at auto "AT+CPIN=\"$pin\"" 2>/dev/null || true)"
if printf "%s\n" "$at_cpin" | grep -qE "(^|[[:space:]])OK([[:space:]]|$)"; then
verified=1
fi
fi
if [ "$verified" = "0" ] && [ -n "$QMICLI_MODEM" ]; then
QMI_CARDS_AFTER="$($QMICLI_MODEM --uim-get-card-status 2>/dev/null || true)"
if [ -n "$QMI_CARDS_AFTER" ]; then
eval "$(parse_uim_card_status "$QMI_CARDS_AFTER" "$slot")"
eval "after_pin1=\$SLOT${slot}_PIN1_STATE"
eval "after_app=\$SLOT${slot}_APP_STATE"
if [ "$after_pin1" = "enabled-verified" ] || [ "$after_pin1" = "disabled" ] || [ "$after_app" = "ready" ]; then
verified=1
fi
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 &
if [ -n "$sim_id" ]; then
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 &
exit 0
fi
exit 1
@@ -583,17 +642,26 @@ case "$cmd" in
echo "Missing PUK or new PIN" >&2
exit 1
fi
prepare_slot_for_pin_op "$slot"
unblocked=0
if detect_qmicli_modem; then
if $QMICLI_MODEM --uim-unblock-pin="PIN1,$puk,$newpin,session-type=card-slot-$slot" >/dev/null 2>&1; 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
if [ "$unblocked" = "0" ] && [ -n "$QMICLI_MODEM" ]; then
if $QMICLI_MODEM --uim-unblock-pin="PIN1,$puk,$newpin,session-type=primary-gw-provisioning" >/dev/null 2>&1; then
unblocked=1
elif $QMICLI_MODEM --uim-unblock-pin="PIN1,$puk,$newpin,session-type=primary-gw-provisioning" >/dev/null 2>&1; then
elif $QMICLI_MODEM --uim-unblock-pin="PIN1,$puk,$newpin,session-type=card-slot-$slot" >/dev/null 2>&1; then
unblocked=1
elif $QMICLI_MODEM --uim-unblock-pin="PIN1,$puk,$newpin" >/dev/null 2>&1; then
unblocked=1
elif $QMICLI_MODEM --dms-uim-unblock-pin="PIN,$puk,$newpin" >/dev/null 2>&1; then
unblocked=1
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
at_cpin="$("$0" at auto "AT+CPIN=\"$puk\",\"$newpin\"" 2>/dev/null || true)"
if printf "%s\n" "$at_cpin" | grep -qE "(^|[[:space:]])OK([[:space:]]|$)"; then
unblocked=1
fi
fi
@@ -601,7 +669,8 @@ case "$cmd" in
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 &
mmcli -m any -e >/dev/null 2>&1 || true
( enable_and_register_modem "$slot" 1 ) >/dev/null 2>&1 </dev/null &
exit 0
fi
exit 1
@@ -615,11 +684,15 @@ case "$cmd" in
echo "Usage: $0 set-pin-lock <1|2> <enable|disable> <pin>" >&2
exit 1
fi
if detect_qmicli_modem; then
prepare_slot_for_pin_op "$slot"
if [ -n "$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
if $QMICLI_MODEM --uim-set-pin-protection="PIN1,$mode,$pin,session-type=primary-gw-provisioning" >/dev/null 2>&1; then
if $QMICLI_MODEM --dms-uim-set-pin-protection="PIN,$mode,$pin" >/dev/null 2>&1; then
exit 0
fi
fi
@@ -642,11 +715,15 @@ case "$cmd" in
echo "Usage: $0 change-pin <1|2> <oldpin> <newpin>" >&2
exit 1
fi
if detect_qmicli_modem; then
prepare_slot_for_pin_op "$slot"
if [ -n "$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
if $QMICLI_MODEM --uim-change-pin="PIN1,$oldpin,$newpin,session-type=primary-gw-provisioning" >/dev/null 2>&1; then
if $QMICLI_MODEM --dms-uim-change-pin="PIN,$oldpin,$newpin" >/dev/null 2>&1; then
exit 0
fi
fi
Binary file not shown.
+42 -31
View File
@@ -601,8 +601,28 @@ int runModemApp(int argc, char** argv) {
lastRefreshMs = nowMs();
};
auto defaultActiveOrPresentSlot = [&]() -> int {
if (status.slots[0].needsPin() || status.slots[0].needsPuk()) return 1;
if (status.slots[1].needsPin() || status.slots[1].needsPuk()) return 2;
if (status.primaryGwSlot >= 1 && status.primaryGwSlot <= 2 &&
status.slots[status.primaryGwSlot - 1].state == "present") {
return status.primaryGwSlot;
}
if (status.slots[1].state == "present" && status.slots[0].state != "present") {
return 2;
}
if (status.slots[0].state == "present" && status.slots[1].state != "present") {
return 1;
}
return std::clamp(status.preferredSlot, 1, 2);
};
auto openPinOrPukModalForSlot = [&](int slotNum) {
targetSlot = std::clamp(slotNum, 1, 2);
slotNum = std::clamp(slotNum, 1, 2);
if (status.slots[slotNum - 1].state != "present") {
slotNum = defaultActiveOrPresentSlot();
}
targetSlot = slotNum;
const auto& s = status.slots[targetSlot - 1];
wizardStep = 0;
revealDigits = false;
@@ -622,14 +642,7 @@ int runModemApp(int argc, char** argv) {
modal = ModalMode::None;
if (a == "unlock" || a == "pin" || a == "puk") {
activeTab = TabId::SimCards;
int lockSlot = (status.primaryGwSlot >= 1 && status.primaryGwSlot <= 2)
? status.primaryGwSlot
: status.preferredSlot;
if (status.slots[0].needsPin() || status.slots[0].needsPuk()) {
lockSlot = 1;
} else if (status.slots[1].needsPin() || status.slots[1].needsPuk()) {
lockSlot = 2;
}
int lockSlot = defaultActiveOrPresentSlot();
simRowSel = lockSlot - 1;
openPinOrPukModalForSlot(lockSlot);
} else if (a == "info" || a == "status" || a == "radio") {
@@ -647,12 +660,7 @@ int runModemApp(int argc, char** argv) {
ussdWaitingReply = false;
} else {
activeTab = TabId::SimCards;
// If active SIM is locked, auto-highlight it
if (status.slots[0].needsPin() || status.slots[0].needsPuk()) {
simRowSel = 0;
} else if (status.slots[1].needsPin() || status.slots[1].needsPuk()) {
simRowSel = 1;
}
simRowSel = defaultActiveOrPresentSlot() - 1;
}
};
@@ -1255,6 +1263,11 @@ int runModemApp(int argc, char** argv) {
std::to_string(slotNum) + " >/dev/null 2>&1", &rc);
runAsyncCmd("sxmo_hook_statusbar.sh modem >/dev/null 2>&1");
refreshData(false);
if (status.slots[slotNum - 1].needsPin() ||
status.slots[slotNum - 1].needsPuk()) {
openPinOrPukModalForSlot(slotNum);
return;
}
if (rc == 0) {
setBanner("Active SIM set to Slot " + std::to_string(slotNum));
} else {
@@ -1445,27 +1458,15 @@ int runModemApp(int argc, char** argv) {
}
switchSimSlotNow(otherSlot);
} else if (row == 3) {
int slot = (status.primaryGwSlot >= 1 && status.primaryGwSlot <= 2)
? status.primaryGwSlot
: 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(defaultActiveOrPresentSlot());
} else if (row == 4) {
targetSlot = (status.primaryGwSlot >= 1 && status.primaryGwSlot <= 2)
? status.primaryGwSlot
: status.preferredSlot;
targetSlot = defaultActiveOrPresentSlot();
wizardStep = 0;
inputPin1.clear();
modalError.clear();
modal = ModalMode::TogglePinLock;
} else if (row == 5) {
targetSlot = (status.primaryGwSlot >= 1 && status.primaryGwSlot <= 2)
? status.primaryGwSlot
: status.preferredSlot;
targetSlot = defaultActiveOrPresentSlot();
wizardStep = 0;
inputPin1.clear();
inputPin2.clear();
@@ -1503,6 +1504,10 @@ int runModemApp(int argc, char** argv) {
if (modal == ModalMode::SimActions) {
int act = actionSel;
modal = ModalMode::None;
if (act >= 1 && act <= 4 &&
status.slots[targetSlot - 1].state != "present") {
targetSlot = defaultActiveOrPresentSlot();
}
if (act == 0) {
switchSimSlotNow(targetSlot);
} else if (act == 1) {
@@ -1537,7 +1542,13 @@ int runModemApp(int argc, char** argv) {
return;
}
if (activeTab == TabId::SimCards) {
targetSlot = (simRowSel == 1) ? 2 : 1;
if (simRowSel == 0) {
targetSlot = 1;
} else if (simRowSel == 1) {
targetSlot = 2;
} else {
targetSlot = defaultActiveOrPresentSlot();
}
actionSel = 0;
modal = ModalMode::SimActions;
} else if (activeTab == TabId::RadioInfo) {