aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2020-08-01 09:59:40 +0200
committerAleksander Morgado <aleksander@aleksander.es>2020-08-28 14:59:06 +0000
commite6ab1182df861e1243f5b93ec334008bec84943e (patch)
tree606fa11772a81a8f56718efbbe4a8176b4e98198
parent924cf1af3c5e1aec1df680d50e4b9ae6dd8e0ba9 (diff)
helpers-qmi: move 'UIM Get Card Status Output' parsing to helpers
This is going to be used in handling the multi-SIM setup, so make it a common helper.
-rw-r--r--src/mm-broadband-modem-qmi.c265
-rw-r--r--src/mm-modem-helpers-qmi.c244
-rw-r--r--src/mm-modem-helpers-qmi.h12
3 files changed, 267 insertions, 254 deletions
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c
index 11b3fb31..caa30d5b 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -680,249 +680,6 @@ modem_load_unlock_required_finish (MMIfaceModem *self,
static void load_unlock_required_context_step (GTask *task);
-/* Used also when loading unlock retries left */
-static gboolean
-uim_get_card_status_output_parse (MMBroadbandModemQmi *self,
- QmiMessageUimGetCardStatusOutput *output,
- MMModemLock *o_lock,
- guint *o_pin1_retries,
- guint *o_puk1_retries,
- guint *o_pin2_retries,
- guint *o_puk2_retries,
- GError **error)
-{
- GArray *cards;
- 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;
-
- /* 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. */
-
- if (!qmi_message_uim_get_card_status_output_get_result (output, error)) {
- g_prefix_error (error, "QMI operation failed: ");
- return FALSE;
- }
-
- qmi_message_uim_get_card_status_output_get_card_status (
- output,
- NULL, /* index_gw_primary */
- NULL, /* index_1x_primary */
- NULL, /* index_gw_secondary */
- NULL, /* index_1x_secondary */
- &cards,
- NULL);
-
- if (cards->len == 0) {
- g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
- "No cards reported");
- return FALSE;
- }
-
- if (cards->len > 1)
- mm_obj_dbg (self, "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 (self, "no applications reported in card [%u]", i);
- n_invalid++;
- break;
- }
-
- if (card->applications->len > 1)
- mm_obj_dbg (self, "multiple applications reported in card [%u]: %u", i, card->applications->len);
-
- for (j = 0; j < card->applications->len; j++) {
- app = &g_array_index (card->applications, QmiMessageUimGetCardStatusOutputCardStatusCardsElementApplicationsElement, j);
-
- if (app->type == QMI_UIM_CARD_APPLICATION_TYPE_UNKNOWN) {
- mm_obj_dbg (self, "mnknown application [%u] found in card [%u]: %s; ignored.",
- j, i, qmi_uim_card_application_state_get_string (app->state));
- continue;
- }
-
- mm_obj_dbg (self, "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));
-
- 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;
- }
-
- sim_usim_found = TRUE;
- }
- }
-
- if (!sim_usim_found) {
- mm_obj_dbg (self, "no SIM/USIM application found in card [%u]", i);
- n_invalid++;
- }
-
- break;
- }
-
- case QMI_UIM_CARD_STATE_ABSENT:
- mm_obj_dbg (self, "card '%u' is absent", i);
- n_absent++;
- break;
-
- case QMI_UIM_CARD_STATE_ERROR:
- default:
- n_error++;
- if (qmi_uim_card_error_get_string (card->error_code) != NULL)
- mm_obj_warn (self, "card '%u' is unusable: %s", i, qmi_uim_card_error_get_string (card->error_code));
- else
- mm_obj_warn (self, "card '%u' is unusable: unknown error", i);
- break;
- }
-
- /* 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);
- return FALSE;
- }
-
- /* Get card/app to use */
- card = &g_array_index (cards, QmiMessageUimGetCardStatusOutputCardStatusCardsElement, card_i);
- app = &g_array_index (card->applications, QmiMessageUimGetCardStatusOutputCardStatusCardsElementApplicationsElement, application_j);
-
- /* If card not ready yet, return RETRY error.
- * If the application state reports needing PIN/PUk, consider that ready as
- * well, and let the logic fall down to check PIN1/PIN2. */
- if (app->state != QMI_UIM_CARD_APPLICATION_STATE_READY &&
- app->state != QMI_UIM_CARD_APPLICATION_STATE_PIN1_OR_UPIN_PIN_REQUIRED &&
- app->state != QMI_UIM_CARD_APPLICATION_STATE_PUK1_OR_UPIN_PUK_REQUIRED &&
- app->state != QMI_UIM_CARD_APPLICATION_STATE_PIN1_BLOCKED) {
- mm_obj_dbg (self, "neither SIM nor USIM are ready");
- g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_RETRY,
- "SIM not ready yet (retry)");
- return FALSE;
- }
-
- /* Report retries if requested to do so */
- if (o_pin1_retries)
- *o_pin1_retries = app->pin1_retries;
- if (o_puk1_retries)
- *o_puk1_retries = app->puk1_retries;
- if (o_pin2_retries)
- *o_pin2_retries = app->pin2_retries;
- if (o_puk2_retries)
- *o_puk2_retries = app->puk2_retries;
-
- /* Early bail out if lock status isn't wanted at this point, so that we
- * don't fail with an error the unlock retries check */
- if (!o_lock)
- return TRUE;
-
- /* Card is ready, what's the lock status? */
-
- /* PIN1 */
- switch (app->pin1_state) {
- case QMI_UIM_PIN_STATE_NOT_INITIALIZED:
- g_set_error (error,
- MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_SIM_WRONG,
- "SIM PIN/PUK status not known yet");
- return FALSE;
-
- case QMI_UIM_PIN_STATE_PERMANENTLY_BLOCKED:
- g_set_error (error,
- MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_SIM_WRONG,
- "SIM PIN/PUK permanently blocked");
- return FALSE;
-
- case QMI_UIM_PIN_STATE_ENABLED_NOT_VERIFIED:
- lock = MM_MODEM_LOCK_SIM_PIN;
- break;
-
- case QMI_UIM_PIN_STATE_BLOCKED:
- lock = MM_MODEM_LOCK_SIM_PUK;
- break;
-
- case QMI_UIM_PIN_STATE_DISABLED:
- case QMI_UIM_PIN_STATE_ENABLED_VERIFIED:
- lock = MM_MODEM_LOCK_NONE;
- break;
-
- default:
- g_set_error (error,
- MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_SIM_WRONG,
- "Unknown SIM PIN/PUK status");
- return FALSE;
- }
-
- /* PIN2 */
- if (lock == MM_MODEM_LOCK_NONE) {
- switch (app->pin2_state) {
- case QMI_UIM_PIN_STATE_NOT_INITIALIZED:
- mm_obj_warn (self, "SIM PIN2/PUK2 status not known yet");
- break;
-
- case QMI_UIM_PIN_STATE_ENABLED_NOT_VERIFIED:
- lock = MM_MODEM_LOCK_SIM_PIN2;
- break;
-
- case QMI_UIM_PIN_STATE_PERMANENTLY_BLOCKED:
- mm_obj_warn (self, "PUK2 permanently blocked");
- /* Fall through */
- case QMI_UIM_PIN_STATE_BLOCKED:
- lock = MM_MODEM_LOCK_SIM_PUK2;
- break;
-
- case QMI_UIM_PIN_STATE_DISABLED:
- case QMI_UIM_PIN_STATE_ENABLED_VERIFIED:
- break;
-
- default:
- mm_obj_warn (self, "unknown SIM PIN2/PUK2 status");
- break;
- }
- }
-
- *o_lock = lock;
- return TRUE;
-}
-
static void
unlock_required_uim_get_card_status_ready (QmiClientUim *client,
GAsyncResult *res,
@@ -945,11 +702,11 @@ unlock_required_uim_get_card_status_ready (QmiClientUim *client,
return;
}
- if (!uim_get_card_status_output_parse (self,
- output,
- &lock,
- NULL, NULL, NULL, NULL,
- &error)) {
+ if (!mm_qmi_uim_get_card_status_output_parse (self,
+ output,
+ &lock,
+ NULL, NULL, NULL, NULL,
+ &error)) {
/* The device may report a SIM NOT INSERTED error if we're querying the
* card status soon after power on. We'll let the Modem interface generic
* logic retry loading the info a bit later if that's the case. This will
@@ -1197,12 +954,12 @@ unlock_retries_uim_get_card_status_ready (QmiClientUim *client,
return;
}
- if (!uim_get_card_status_output_parse (self,
- output,
- NULL,
- &pin1_retries, &puk1_retries,
- &pin2_retries, &puk2_retries,
- &error)) {
+ if (!mm_qmi_uim_get_card_status_output_parse (self,
+ output,
+ NULL,
+ &pin1_retries, &puk1_retries,
+ &pin2_retries, &puk2_retries,
+ &error)) {
g_task_return_error (task, error);
g_object_unref (task);
return;
diff --git a/src/mm-modem-helpers-qmi.c b/src/mm-modem-helpers-qmi.c
index d339f489..76e437bc 100644
--- a/src/mm-modem-helpers-qmi.c
+++ b/src/mm-modem-helpers-qmi.c
@@ -1791,3 +1791,247 @@ mm_firmware_unique_id_to_qmi_unique_id (const gchar *unique_id,
"Unexpected unique id length: %u", len);
return NULL;
}
+
+/*****************************************************************************/
+
+gboolean
+mm_qmi_uim_get_card_status_output_parse (gpointer log_object,
+ QmiMessageUimGetCardStatusOutput *output,
+ MMModemLock *o_lock,
+ guint *o_pin1_retries,
+ guint *o_puk1_retries,
+ guint *o_pin2_retries,
+ guint *o_puk2_retries,
+ GError **error)
+{
+ GArray *cards;
+ 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;
+
+ /* 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. */
+
+ if (!qmi_message_uim_get_card_status_output_get_result (output, error)) {
+ g_prefix_error (error, "QMI operation failed: ");
+ return FALSE;
+ }
+
+ qmi_message_uim_get_card_status_output_get_card_status (
+ output,
+ NULL, /* index_gw_primary */
+ NULL, /* index_1x_primary */
+ NULL, /* index_gw_secondary */
+ NULL, /* index_1x_secondary */
+ &cards,
+ NULL);
+
+ if (cards->len == 0) {
+ g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_FAILED,
+ "No cards reported");
+ 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;
+ }
+
+ if (card->applications->len > 1)
+ mm_obj_dbg (log_object, "multiple applications reported in card [%u]: %u", i, card->applications->len);
+
+ for (j = 0; j < card->applications->len; j++) {
+ app = &g_array_index (card->applications, QmiMessageUimGetCardStatusOutputCardStatusCardsElementApplicationsElement, j);
+
+ 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;
+ }
+
+ 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));
+
+ 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;
+ }
+
+ sim_usim_found = TRUE;
+ }
+ }
+
+ if (!sim_usim_found) {
+ mm_obj_dbg (log_object, "no SIM/USIM application found in card [%u]", i);
+ n_invalid++;
+ }
+
+ break;
+ }
+
+ case QMI_UIM_CARD_STATE_ABSENT:
+ mm_obj_dbg (log_object, "card '%u' is absent", i);
+ n_absent++;
+ break;
+
+ 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;
+ }
+
+ /* 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);
+ return FALSE;
+ }
+
+ /* Get card/app to use */
+ card = &g_array_index (cards, QmiMessageUimGetCardStatusOutputCardStatusCardsElement, card_i);
+ app = &g_array_index (card->applications, QmiMessageUimGetCardStatusOutputCardStatusCardsElementApplicationsElement, application_j);
+
+ /* If card not ready yet, return RETRY error.
+ * If the application state reports needing PIN/PUk, consider that ready as
+ * well, and let the logic fall down to check PIN1/PIN2. */
+ if (app->state != QMI_UIM_CARD_APPLICATION_STATE_READY &&
+ app->state != QMI_UIM_CARD_APPLICATION_STATE_PIN1_OR_UPIN_PIN_REQUIRED &&
+ app->state != QMI_UIM_CARD_APPLICATION_STATE_PUK1_OR_UPIN_PUK_REQUIRED &&
+ app->state != QMI_UIM_CARD_APPLICATION_STATE_PIN1_BLOCKED) {
+ mm_obj_dbg (log_object, "neither SIM nor USIM are ready");
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_RETRY,
+ "SIM not ready yet (retry)");
+ return FALSE;
+ }
+
+ /* Report retries if requested to do so */
+ if (o_pin1_retries)
+ *o_pin1_retries = app->pin1_retries;
+ if (o_puk1_retries)
+ *o_puk1_retries = app->puk1_retries;
+ if (o_pin2_retries)
+ *o_pin2_retries = app->pin2_retries;
+ if (o_puk2_retries)
+ *o_puk2_retries = app->puk2_retries;
+
+ /* Early bail out if lock status isn't wanted at this point, so that we
+ * don't fail with an error the unlock retries check */
+ if (!o_lock)
+ return TRUE;
+
+ /* Card is ready, what's the lock status? */
+
+ /* PIN1 */
+ switch (app->pin1_state) {
+ case QMI_UIM_PIN_STATE_NOT_INITIALIZED:
+ g_set_error (error,
+ MM_MOBILE_EQUIPMENT_ERROR,
+ MM_MOBILE_EQUIPMENT_ERROR_SIM_WRONG,
+ "SIM PIN/PUK status not known yet");
+ return FALSE;
+
+ case QMI_UIM_PIN_STATE_PERMANENTLY_BLOCKED:
+ g_set_error (error,
+ MM_MOBILE_EQUIPMENT_ERROR,
+ MM_MOBILE_EQUIPMENT_ERROR_SIM_WRONG,
+ "SIM PIN/PUK permanently blocked");
+ return FALSE;
+
+ case QMI_UIM_PIN_STATE_ENABLED_NOT_VERIFIED:
+ lock = MM_MODEM_LOCK_SIM_PIN;
+ break;
+
+ case QMI_UIM_PIN_STATE_BLOCKED:
+ lock = MM_MODEM_LOCK_SIM_PUK;
+ break;
+
+ case QMI_UIM_PIN_STATE_DISABLED:
+ case QMI_UIM_PIN_STATE_ENABLED_VERIFIED:
+ lock = MM_MODEM_LOCK_NONE;
+ break;
+
+ default:
+ g_set_error (error,
+ MM_MOBILE_EQUIPMENT_ERROR,
+ MM_MOBILE_EQUIPMENT_ERROR_SIM_WRONG,
+ "Unknown SIM PIN/PUK status");
+ return FALSE;
+ }
+
+ /* PIN2 */
+ if (lock == MM_MODEM_LOCK_NONE) {
+ switch (app->pin2_state) {
+ case QMI_UIM_PIN_STATE_NOT_INITIALIZED:
+ mm_obj_warn (log_object, "SIM PIN2/PUK2 status not known yet");
+ break;
+
+ case QMI_UIM_PIN_STATE_ENABLED_NOT_VERIFIED:
+ lock = MM_MODEM_LOCK_SIM_PIN2;
+ break;
+
+ case QMI_UIM_PIN_STATE_PERMANENTLY_BLOCKED:
+ mm_obj_warn (log_object, "PUK2 permanently blocked");
+ /* Fall through */
+ case QMI_UIM_PIN_STATE_BLOCKED:
+ lock = MM_MODEM_LOCK_SIM_PUK2;
+ break;
+
+ case QMI_UIM_PIN_STATE_DISABLED:
+ case QMI_UIM_PIN_STATE_ENABLED_VERIFIED:
+ break;
+
+ default:
+ mm_obj_warn (log_object, "unknown SIM PIN2/PUK2 status");
+ break;
+ }
+ }
+
+ *o_lock = lock;
+ return TRUE;
+}
diff --git a/src/mm-modem-helpers-qmi.h b/src/mm-modem-helpers-qmi.h
index 42cb6711..ae52afb8 100644
--- a/src/mm-modem-helpers-qmi.h
+++ b/src/mm-modem-helpers-qmi.h
@@ -154,4 +154,16 @@ gchar *mm_qmi_unique_id_to_firmware_unique_id (GArray *qmi_unique_id,
GArray *mm_firmware_unique_id_to_qmi_unique_id (const gchar *unique_id,
GError **error);
+/*****************************************************************************/
+/* Common UIM Get Card Status parsing */
+
+gboolean mm_qmi_uim_get_card_status_output_parse (gpointer log_object,
+ QmiMessageUimGetCardStatusOutput *output,
+ MMModemLock *o_lock,
+ guint *o_pin1_retries,
+ guint *o_puk1_retries,
+ guint *o_pin2_retries,
+ guint *o_puk2_retries,
+ GError **error);
+
#endif /* MM_MODEM_HELPERS_QMI_H */