uqmi: add illegal SIM state recovery
[openwrt/staging/jow.git] / package / network / utils / uqmi / files / lib / netifd / proto / qmi.sh
index 6c5104bccd834738abd1cc0ec1e71388e496d0cd..52515dd9c1efa088620cdcd59e61e28a83a88143 100755 (executable)
@@ -83,6 +83,8 @@ proto_qmi_setup() {
 
        echo "Waiting for SIM initialization"
        local uninitialized_timeout=0
+       # timeout 3s for first call to avoid hanging uqmi
+       uqmi -d "$device" --get-pin-status -t 3000 > /dev/null 2>&1
        while uqmi -s -d "$device" --get-pin-status | grep '"UIM uninitialized"' > /dev/null; do
                [ -e "$device" ] || return 1
                if [ "$uninitialized_timeout" -lt "$timeout" -o "$timeout" = "0" ]; then
@@ -96,6 +98,37 @@ proto_qmi_setup() {
                fi
        done
 
+       # Check if UIM application is stuck in illegal state
+       local uim_state_timeout=0
+       while true; do
+               json_load "$(uqmi -s -d "$device" --uim-get-sim-state)"
+               json_get_var card_application_state card_application_state
+
+               # SIM card is either completely absent or state is labeled as illegal
+               # Try to power-cycle the SIM card to recover from this state
+               if [ -z "$card_application_state" -o "$card_application_state" = "illegal" ]; then
+                       echo "SIM in illegal state - Power-cycling SIM"
+
+                       # Try to reset SIM application
+                       uqmi -d "$device" --uim-power-off --uim-slot 1
+                       sleep 3
+                       uqmi -d "$device" --uim-power-on --uim-slot 1
+
+                       if [ "$uim_state_timeout" -lt "$timeout" ] || [ "$timeout" = "0" ]; then
+                               let uim_state_timeout++
+                               sleep 1
+                               continue
+                       fi
+
+                       # Recovery failed
+                       proto_notify_error "$interface" SIM_ILLEGAL_STATE
+                       proto_block_restart "$interface"
+                       return 1
+               else
+                       break
+               fi
+       done
+
        if uqmi -s -d "$device" --uim-get-sim-state | grep -q '"Not supported"\|"Invalid QMI command"' &&
           uqmi -s -d "$device" --get-pin-status | grep -q '"Not supported"\|"Invalid QMI command"' ; then
                [ -n "$pincode" ] && {
@@ -245,7 +278,6 @@ proto_qmi_setup() {
                fi
 
                proto_notify_error "$interface" NETWORK_REGISTRATION_FAILED
-               proto_block_restart "$interface"
                return 1
        done