From be81f7e5a21cd42b708ab3b5af5c56cd4fdff35c Mon Sep 17 00:00:00 2001 From: Ben Chan Date: Thu, 11 Oct 2018 11:36:00 -0700 Subject: sim-qmi: use QMI UIM service to read IMSI if needed If a QMI modem doesn't support the deprecated DMS_UIM_GET_IMSI command, use the UIM_READ_TRANSPARENT command to read EFimsi on the SIM to determine the IMSI. --- src/mm-sim-qmi.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 70 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/mm-sim-qmi.c b/src/mm-sim-qmi.c index e7b90d70..9e7459d0 100644 --- a/src/mm-sim-qmi.c +++ b/src/mm-sim-qmi.c @@ -313,6 +313,55 @@ load_imsi_finish (MMBaseSim *self, return g_task_propagate_pointer (G_TASK (res), error); } +static void +uim_get_imsi_ready (QmiClientUim *client, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + GArray *read_result; + gchar *imsi; + + read_result = uim_read_finish (client, res, &error); + if (!read_result) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + imsi = mm_bcd_to_string ((const guint8 *) read_result->data, read_result->len); + g_assert (imsi); + if (strlen (imsi) < 3) + g_task_return_new_error (task, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "IMSI is malformed"); + else + /* EFimsi contains a length byte, follwed by a nibble for parity, + * and then followed by the actual IMSI in BCD. After converting + * the BCD into a decimal string, we simply skip the first 3 + * decimal digits to obtain the IMSI. */ + g_task_return_pointer (task, g_strdup (imsi + 3), g_free); + g_object_unref (task); + + g_free (imsi); + g_array_unref (read_result); +} + +static void +uim_get_imsi (MMSimQmi *self, + GTask *task) +{ + static const guint16 file_path[] = { 0x3F00, 0x7FFF }; + + uim_read (self, + 0x6F07, + file_path, + G_N_ELEMENTS (file_path), + (GAsyncReadyCallback)uim_get_imsi_ready, + task); +} + static void dms_uim_get_imsi_ready (QmiClientDms *client, GAsyncResult *res, @@ -342,20 +391,16 @@ dms_uim_get_imsi_ready (QmiClientDms *client, } static void -load_imsi (MMBaseSim *self, - GAsyncReadyCallback callback, - gpointer user_data) +dms_uim_get_imsi (MMSimQmi *self, + GTask *task) { - GTask *task; QmiClient *client = NULL; - task = g_task_new (self, NULL, callback, user_data); if (!ensure_qmi_client (task, - MM_SIM_QMI (self), + self, QMI_SERVICE_DMS, &client)) return; - mm_dbg ("loading IMSI..."); qmi_client_dms_uim_get_imsi (QMI_CLIENT_DMS (client), NULL, 5, @@ -364,6 +409,24 @@ load_imsi (MMBaseSim *self, task); } +static void +load_imsi (MMBaseSim *_self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + MMSimQmi *self; + GTask *task; + + self = MM_SIM_QMI (_self); + task = g_task_new (self, NULL, callback, user_data); + + mm_dbg ("loading IMSI..."); + if (!self->priv->dms_uim_deprecated) + dms_uim_get_imsi (self, task); + else + uim_get_imsi (self, task); +} + /*****************************************************************************/ /* Load operator identifier */ -- cgit v1.2.3-70-g09d2