sim-qmi: use QMI UIM service to read ICCID if needed

If a QMI modem doesn't support the deprecated DMS_UIM_GET_ICCID command,
use the UIM_READ_TRANSPARENT command to read EFiccid on the SIM to
determine the ICCID.
This commit is contained in:
Ben Chan
2018-10-11 11:36:00 -07:00
parent 942bdeaec2
commit 055177fdf0

View File

@@ -91,6 +91,106 @@ ensure_qmi_client (GTask *task,
/*****************************************************************************/ /*****************************************************************************/
/* Load SIM ID (ICCID) */ /* Load SIM ID (ICCID) */
static GArray *
uim_read_finish (QmiClientUim *client,
GAsyncResult *res,
GError **error)
{
return g_task_propagate_pointer (G_TASK (res), error);
}
static void
uim_read_ready (QmiClientUim *client,
GAsyncResult *res,
GTask *task)
{
QmiMessageUimReadTransparentOutput *output;
GError *error = NULL;
output = qmi_client_uim_read_transparent_finish (client, res, &error);
if (!output) {
g_prefix_error (&error, "QMI operation failed: ");
g_task_return_error (task, error);
} else if (!qmi_message_uim_read_transparent_output_get_result (output, &error)) {
g_prefix_error (&error, "Couldn't read data from UIM: ");
g_task_return_error (task, error);
} else {
GArray *read_result = NULL;
qmi_message_uim_read_transparent_output_get_read_result (output, &read_result, NULL);
if (read_result)
g_task_return_pointer (task,
g_array_ref (read_result),
(GDestroyNotify) g_array_unref);
else
g_task_return_new_error (task,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Read malformed data from UIM");
}
if (output)
qmi_message_uim_read_transparent_output_unref (output);
g_object_unref (task);
}
static void
uim_read (MMSimQmi *self,
guint16 file_id,
const guint16 *file_path,
gsize file_path_len,
GAsyncReadyCallback callback,
gpointer user_data)
{
GTask *task;
QmiClient *client = NULL;
GArray *file_path_bytes;
gsize i;
QmiMessageUimReadTransparentInput *input;
task = g_task_new (self, NULL, callback, user_data);
if (!ensure_qmi_client (task,
self,
QMI_SERVICE_UIM, &client))
return;
file_path_bytes = g_array_sized_new (FALSE, FALSE, 1, file_path_len * 2);
for (i = 0; i < file_path_len; ++i) {
guint8 byte;
byte = file_path[i] & 0xFF;
g_array_append_val (file_path_bytes, byte);
byte = (file_path[i] >> 8) & 0xFF;
g_array_append_val (file_path_bytes, byte);
}
input = qmi_message_uim_read_transparent_input_new ();
qmi_message_uim_read_transparent_input_set_session_information (
input,
QMI_UIM_SESSION_TYPE_PRIMARY_GW_PROVISIONING,
"",
NULL);
qmi_message_uim_read_transparent_input_set_file (input,
file_id,
file_path_bytes,
NULL);
qmi_message_uim_read_transparent_input_set_read_information (input,
0,
0,
NULL);
g_array_unref (file_path_bytes);
qmi_client_uim_read_transparent (QMI_CLIENT_UIM (client),
input,
10,
NULL,
(GAsyncReadyCallback)uim_read_ready,
task);
qmi_message_uim_read_transparent_input_unref (input);
}
static gchar * static gchar *
load_sim_identifier_finish (MMBaseSim *self, load_sim_identifier_finish (MMBaseSim *self,
GAsyncResult *res, GAsyncResult *res,
@@ -99,6 +199,44 @@ load_sim_identifier_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_iccid_ready (QmiClientUim *client,
GAsyncResult *res,
GTask *task)
{
GError *error = NULL;
GArray *read_result;
gchar *iccid;
read_result = uim_read_finish (client, res, &error);
if (!read_result) {
g_task_return_error (task, error);
g_object_unref (task);
return;
}
iccid = mm_bcd_to_string ((const guint8 *) read_result->data, read_result->len);
g_assert (iccid);
g_task_return_pointer (task, iccid, g_free);
g_object_unref (task);
g_array_unref (read_result);
}
static void
uim_get_iccid (MMSimQmi *self,
GTask *task)
{
static const guint16 file_path[] = { 0x3F00 };
uim_read (self,
0x2FE2,
file_path,
G_N_ELEMENTS (file_path),
(GAsyncReadyCallback)uim_get_iccid_ready,
task);
}
static void static void
dms_uim_get_iccid_ready (QmiClientDms *client, dms_uim_get_iccid_ready (QmiClientDms *client,
GAsyncResult *res, GAsyncResult *res,
@@ -128,20 +266,16 @@ dms_uim_get_iccid_ready (QmiClientDms *client,
} }
static void static void
load_sim_identifier (MMBaseSim *self, dms_uim_get_iccid (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 SIM identifier...");
qmi_client_dms_uim_get_iccid (QMI_CLIENT_DMS (client), qmi_client_dms_uim_get_iccid (QMI_CLIENT_DMS (client),
NULL, NULL,
5, 5,
@@ -150,6 +284,24 @@ load_sim_identifier (MMBaseSim *self,
task); task);
} }
static void
load_sim_identifier (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 SIM identifier...");
if (!self->priv->dms_uim_deprecated)
dms_uim_get_iccid (self, task);
else
uim_get_iccid (self, task);
}
/*****************************************************************************/ /*****************************************************************************/
/* Load IMSI */ /* Load IMSI */