diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2020-08-01 09:59:43 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2020-08-28 14:59:06 +0000 |
commit | 89b6e811b984f2f9f6e0eea652246a58e3200c8f (patch) | |
tree | d8f861a7894334559126c3253495d850cfb1938b /src | |
parent | e6ab1182df861e1243f5b93ec334008bec84943e (diff) |
helpers-qmi: fix detection of primary active SIM status
The original logic that parsed the 'UIM Get Card Status Output' did a
bit of guessing to decide what was the current lock status to consider
in the modem. This guessing was fine on systems with a single SIM
slot, but it was very wrong as soon as multiple SIMs had to be
considered.
In a Multi-SIM Multi-Standby setup, with multiple SIMs reported as
active, we should look for the one flagged as "GW primary" to consider
it the primary SIM card of the system,the one required to start a data
connection.
We explicitly ignore the ones flagged as "1X primary", as we don't
consider a SIM card required in CDMA/EVDO setups.
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-modem-helpers-qmi.c | 175 |
1 files changed, 80 insertions, 95 deletions
diff --git a/src/mm-modem-helpers-qmi.c b/src/mm-modem-helpers-qmi.c index 76e437bc..5f5afb36 100644 --- a/src/mm-modem-helpers-qmi.c +++ b/src/mm-modem-helpers-qmi.c @@ -1804,20 +1804,17 @@ mm_qmi_uim_get_card_status_output_parse (gpointer log_ guint *o_puk2_retries, GError **error) { - GArray *cards; - QmiMessageUimGetCardStatusOutputCardStatusCardsElement *card; + QmiMessageUimGetCardStatusOutputCardStatusCardsElement *card; QmiMessageUimGetCardStatusOutputCardStatusCardsElementApplicationsElement *app; - MMModemLock lock = MM_MODEM_LOCK_UNKNOWN; - guint i; - gint card_i = -1; - gint application_j = -1; - guint n_absent = 0; - guint n_error = 0; - guint n_invalid = 0; + GArray *cards; + guint16 index_gw_primary = 0xFFFF; + guint8 gw_primary_slot_i = 0; + guint8 gw_primary_application_i = 0; + MMModemLock lock = MM_MODEM_LOCK_UNKNOWN; /* This command supports MULTIPLE cards with MULTIPLE applications each. For our - * purposes, we're going to consider as the SIM to use the first card present - * with a SIM/USIM application. */ + * purposes, we're going to consider as the SIM to use the one identified as + * 'primary GW' exclusively. We don't really support Dual Sim Dual Standby yet. */ if (!qmi_message_uim_get_card_status_output_get_result (output, error)) { g_prefix_error (error, "QMI operation failed: "); @@ -1826,7 +1823,7 @@ mm_qmi_uim_get_card_status_output_parse (gpointer log_ qmi_message_uim_get_card_status_output_get_card_status ( output, - NULL, /* index_gw_primary */ + &index_gw_primary, NULL, /* index_1x_primary */ NULL, /* index_gw_secondary */ NULL, /* index_1x_secondary */ @@ -1839,103 +1836,91 @@ mm_qmi_uim_get_card_status_output_parse (gpointer log_ return FALSE; } - if (cards->len > 1) - mm_obj_dbg (log_object, "multiple cards reported: %u", cards->len); - - /* All KNOWN applications in all cards will need to be in READY state for us - * to consider UNLOCKED */ - for (i = 0; i < cards->len; i++) { - card = &g_array_index (cards, QmiMessageUimGetCardStatusOutputCardStatusCardsElement, i); - - switch (card->card_state) { - case QMI_UIM_CARD_STATE_PRESENT: { - guint j; - gboolean sim_usim_found = FALSE; - - if (card->applications->len == 0) { - mm_obj_dbg (log_object, "no applications reported in card [%u]", i); - n_invalid++; - break; - } + /* Look for the primary GW slot and application. + * If we don't have valid GW primary slot index and application index, assume + * we're missing the SIM altogether */ + gw_primary_slot_i = ((index_gw_primary & 0xFF00) >> 8); + gw_primary_application_i = ((index_gw_primary & 0x00FF)); - if (card->applications->len > 1) - mm_obj_dbg (log_object, "multiple applications reported in card [%u]: %u", i, card->applications->len); + if (gw_primary_slot_i == 0xFF) { + g_set_error (error, + MM_MOBILE_EQUIPMENT_ERROR, + MM_MOBILE_EQUIPMENT_ERROR_SIM_NOT_INSERTED, + "GW primary session index unknown"); + return FALSE; + } + mm_obj_dbg (log_object, "GW primary session index: %u", gw_primary_slot_i); - for (j = 0; j < card->applications->len; j++) { - app = &g_array_index (card->applications, QmiMessageUimGetCardStatusOutputCardStatusCardsElementApplicationsElement, j); + if (gw_primary_application_i == 0xFF) { + g_set_error (error, + MM_MOBILE_EQUIPMENT_ERROR, + MM_MOBILE_EQUIPMENT_ERROR_SIM_NOT_INSERTED, + "GW primary application index unknown"); + return FALSE; + } + mm_obj_dbg (log_object, "GW primary application index: %u", gw_primary_application_i); - if (app->type == QMI_UIM_CARD_APPLICATION_TYPE_UNKNOWN) { - mm_obj_dbg (log_object, "mnknown application [%u] found in card [%u]: %s; ignored.", - j, i, qmi_uim_card_application_state_get_string (app->state)); - continue; - } + /* Validate slot index */ + if (gw_primary_slot_i >= cards->len) { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Invalid GW primary session index: %u", + gw_primary_slot_i); + return FALSE; + } - mm_obj_dbg (log_object, "application '%s' [%u] in card [%u]: %s", - qmi_uim_card_application_type_get_string (app->type), j, i, qmi_uim_card_application_state_get_string (app->state)); + /* Get card at slot */ + card = &g_array_index (cards, QmiMessageUimGetCardStatusOutputCardStatusCardsElement, gw_primary_slot_i); - if (app->type == QMI_UIM_CARD_APPLICATION_TYPE_SIM || app->type == QMI_UIM_CARD_APPLICATION_TYPE_USIM) { - /* We found the card/app pair to use! Only keep the first found, - * but still, keep on looping to log about the remaining ones */ - if (card_i < 0 && application_j < 0) { - card_i = i; - application_j = j; - } + if (card->card_state == QMI_UIM_CARD_STATE_ABSENT) { + g_set_error (error, + MM_MOBILE_EQUIPMENT_ERROR, + MM_MOBILE_EQUIPMENT_ERROR_SIM_NOT_INSERTED, + "No card found"); + return FALSE; + } - sim_usim_found = TRUE; - } - } + if (card->card_state == QMI_UIM_CARD_STATE_ERROR) { + const gchar *card_error; - if (!sim_usim_found) { - mm_obj_dbg (log_object, "no SIM/USIM application found in card [%u]", i); - n_invalid++; - } + card_error = qmi_uim_card_error_get_string (card->error_code); + g_set_error (error, + MM_MOBILE_EQUIPMENT_ERROR, + MM_MOBILE_EQUIPMENT_ERROR_SIM_WRONG, + "Card error: %s", card_error ? card_error : "unknown error"); + return FALSE; + } - break; - } + if (card->card_state != QMI_UIM_CARD_STATE_PRESENT) { + g_set_error (error, + MM_MOBILE_EQUIPMENT_ERROR, + MM_MOBILE_EQUIPMENT_ERROR_SIM_WRONG, + "Card error: unexpected card state: 0x%x", card->card_state); + return FALSE; + } - case QMI_UIM_CARD_STATE_ABSENT: - mm_obj_dbg (log_object, "card '%u' is absent", i); - n_absent++; - break; + /* Card is present */ - case QMI_UIM_CARD_STATE_ERROR: - default: - n_error++; - if (qmi_uim_card_error_get_string (card->error_code) != NULL) - mm_obj_warn (log_object, "card '%u' is unusable: %s", i, qmi_uim_card_error_get_string (card->error_code)); - else - mm_obj_warn (log_object, "card '%u' is unusable: unknown error", i); - break; - } + if (card->applications->len == 0) { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "No applications reported in card"); + return FALSE; + } - /* go on to next card */ - } - - /* If we found no card/app to use, we need to report an error */ - if (card_i < 0 || application_j < 0) { - /* If not a single card found, report SIM not inserted */ - if (n_absent > 0 && !n_error && !n_invalid) - g_set_error (error, - MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_SIM_NOT_INSERTED, - "No card found"); - else if (n_error > 0) - g_set_error (error, - MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_SIM_WRONG, - "Card error"); - else - g_set_error (error, - MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_SIM_FAILURE, - "Card failure: %u absent, %u errors, %u invalid", - n_absent, n_error, n_invalid); + /* Validate application index */ + if (gw_primary_application_i >= card->applications->len) { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Invalid GW primary application index: %u", + gw_primary_application_i); return FALSE; } - /* Get card/app to use */ - card = &g_array_index (cards, QmiMessageUimGetCardStatusOutputCardStatusCardsElement, card_i); - app = &g_array_index (card->applications, QmiMessageUimGetCardStatusOutputCardStatusCardsElementApplicationsElement, application_j); + app = &g_array_index (card->applications, QmiMessageUimGetCardStatusOutputCardStatusCardsElementApplicationsElement, gw_primary_application_i); + if ((app->type != QMI_UIM_CARD_APPLICATION_TYPE_SIM) && (app->type != QMI_UIM_CARD_APPLICATION_TYPE_USIM)) { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Unsupported application type found in GW primary application index: %s", + qmi_uim_card_application_type_get_string (app->type)); + return FALSE; + } /* If card not ready yet, return RETRY error. * If the application state reports needing PIN/PUk, consider that ready as |