diff --git a/overlay/rootfs/usr/lib/dwm/plugins/modem.so b/overlay/rootfs/usr/lib/dwm/plugins/modem.so index 55cb688..0c0af48 100755 Binary files a/overlay/rootfs/usr/lib/dwm/plugins/modem.so and b/overlay/rootfs/usr/lib/dwm/plugins/modem.so differ diff --git a/overlay/rootfs/usr/libexec/msm-modem-uim-selection b/overlay/rootfs/usr/libexec/msm-modem-uim-selection index 4d7f6c9..7f486c4 100755 --- a/overlay/rootfs/usr/libexec/msm-modem-uim-selection +++ b/overlay/rootfs/usr/libexec/msm-modem-uim-selection @@ -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 2>&1 /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 2>&1 &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 2>&1 || true + fi + mmcli -m any -e >/dev/null 2>&1 || true + ( enable_and_register_modem "$slot" 1 ) >/dev/null 2>&1 &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 2>&1 || true + ( enable_and_register_modem "$slot" 1 ) >/dev/null 2>&1 " >&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> " >&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 diff --git a/prebuilt/sxmo-x11/usr/lib/dwm/plugins/modem.so b/prebuilt/sxmo-x11/usr/lib/dwm/plugins/modem.so index 55cb688..0c0af48 100755 Binary files a/prebuilt/sxmo-x11/usr/lib/dwm/plugins/modem.so and b/prebuilt/sxmo-x11/usr/lib/dwm/plugins/modem.so differ diff --git a/src/dwm-plugins/modem_plugin.cpp b/src/dwm-plugins/modem_plugin.cpp index 3ad6723..0c25eb3 100644 --- a/src/dwm-plugins/modem_plugin.cpp +++ b/src/dwm-plugins/modem_plugin.cpp @@ -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) {