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.
This commit is contained in:
Ben Chan
2018-10-11 11:36:00 -07:00
parent 055177fdf0
commit be81f7e5a2

View File

@@ -313,6 +313,55 @@ load_imsi_finish (MMBaseSim *self,
return g_task_propagate_pointer (G_TASK (res), error); 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 static void
dms_uim_get_imsi_ready (QmiClientDms *client, dms_uim_get_imsi_ready (QmiClientDms *client,
GAsyncResult *res, GAsyncResult *res,
@@ -342,20 +391,16 @@ dms_uim_get_imsi_ready (QmiClientDms *client,
} }
static void static void
load_imsi (MMBaseSim *self, dms_uim_get_imsi (MMSimQmi *self,
GAsyncReadyCallback callback, GTask *task)
gpointer user_data)
{ {
GTask *task;
QmiClient *client = NULL; QmiClient *client = NULL;
task = g_task_new (self, NULL, callback, user_data);
if (!ensure_qmi_client (task, if (!ensure_qmi_client (task,
MM_SIM_QMI (self), self,
QMI_SERVICE_DMS, &client)) QMI_SERVICE_DMS, &client))
return; return;
mm_dbg ("loading IMSI...");
qmi_client_dms_uim_get_imsi (QMI_CLIENT_DMS (client), qmi_client_dms_uim_get_imsi (QMI_CLIENT_DMS (client),
NULL, NULL,
5, 5,
@@ -364,6 +409,24 @@ load_imsi (MMBaseSim *self,
task); 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 */ /* Load operator identifier */