shared-qmi: avoid jumps in the SIM hot swap setup state machine

Always transition to the next step, and decide what to do based on the
state tracked by the previously run steps.
This commit is contained in:
Aleksander Morgado
2022-07-16 14:56:09 +02:00
committed by Aleksander Morgado
parent 21d24657eb
commit b7da236567

View File

@@ -3579,6 +3579,10 @@ typedef enum {
typedef struct { typedef struct {
SetupSimHotSwapStep step; SetupSimHotSwapStep step;
gboolean register_slot_status_supported;
gboolean get_slot_status_supported;
gboolean refresh_all_supported;
gboolean refresh_file_supported;
} SetupSimHotSwapContext; } SetupSimHotSwapContext;
static void setup_sim_hot_swap_step (GTask *task); static void setup_sim_hot_swap_step (GTask *task);
@@ -3872,35 +3876,26 @@ uim_refresh_register_file_ready (QmiClientUim *client,
GTask *task) GTask *task)
{ {
MMSharedQmi *self; MMSharedQmi *self;
Private *priv;
g_autoptr(QmiMessageUimRefreshRegisterOutput) output = NULL; g_autoptr(QmiMessageUimRefreshRegisterOutput) output = NULL;
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
SetupSimHotSwapContext *ctx; SetupSimHotSwapContext *ctx;
self = g_task_get_source_object (task); self = g_task_get_source_object (task);
priv = get_private (self);
ctx = g_task_get_task_data (task); ctx = g_task_get_task_data (task);
output = qmi_client_uim_refresh_register_finish (client, res, &error); output = qmi_client_uim_refresh_register_finish (client, res, &error);
if (!output || !qmi_message_uim_refresh_register_output_get_result (output, &error)) { if (!output || !qmi_message_uim_refresh_register_output_get_result (output, &error))
mm_obj_dbg (self, "file refresh registration using 'refresh register' failed: %s", error->message); mm_obj_dbg (self, "file refresh registration using 'refresh register' failed: %s", error->message);
g_clear_object (&priv->uim_client); else {
g_task_return_new_error (task, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_NOT_SUPPORTED,
"SIM hot swap detection not supported by modem");
g_object_unref (task);
return;
}
mm_obj_dbg (self, "file refresh registered using 'refresh register'"); mm_obj_dbg (self, "file refresh registered using 'refresh register'");
ctx->refresh_file_supported = TRUE;
}
/* Go on to next step */ /* Go on to next step */
ctx->step++; ctx->step++;
setup_sim_hot_swap_step (task); setup_sim_hot_swap_step (task);
} }
/* This is the last resort if 'refresh register all' does not work. It works
* on some older modems. Those modems may not also support QMI_UIM_SESSION_TYPE_CARD_SLOT_1
* so we'll use QMI_UIM_SESSION_TYPE_PRIMARY_GW_PROVISIONING */
static void static void
uim_refresh_register_file (GTask *task, uim_refresh_register_file (GTask *task,
guint16 file_id, guint16 file_id,
@@ -3920,6 +3915,10 @@ uim_refresh_register_file (GTask *task,
self = g_task_get_source_object (task); self = g_task_get_source_object (task);
priv = get_private (MM_SHARED_QMI (self)); priv = get_private (MM_SHARED_QMI (self));
/* This is the last resort if 'refresh register all' does not work. It works
* on some older modems. Those modems may not also support QMI_UIM_SESSION_TYPE_CARD_SLOT_1
* so we'll use QMI_UIM_SESSION_TYPE_PRIMARY_GW_PROVISIONING */
mm_obj_dbg (self, "register for refresh file indication"); mm_obj_dbg (self, "register for refresh file indication");
placeholder_aid = g_array_new (FALSE, FALSE, sizeof (guint8)); placeholder_aid = g_array_new (FALSE, FALSE, sizeof (guint8));
@@ -3978,16 +3977,14 @@ uim_refresh_register_all_ready (QmiClientUim *client,
output = qmi_client_uim_refresh_register_all_finish (client, res, &error); output = qmi_client_uim_refresh_register_all_finish (client, res, &error);
if (!output || !qmi_message_uim_refresh_register_all_output_get_result (output, &error)) { if (!output || !qmi_message_uim_refresh_register_all_output_get_result (output, &error)) {
/* As last resort, if 'refresh register all' fails, try a plain 'refresh register'.
* Some older modems may not support 'refresh register all'. */
mm_obj_dbg (self, "refresh register all operation failed: %s", error->message); mm_obj_dbg (self, "refresh register all operation failed: %s", error->message);
ctx->step++;
} else { } else {
/* Jump to setup refresh indication signal */ /* Jump to setup refresh indication signal */
mm_obj_dbg (self, "registered for all SIM refresh events"); mm_obj_dbg (self, "registered for all SIM refresh events");
ctx->step = SETUP_SIM_HOT_SWAP_STEP_UIM_REFRESH_INDICATION; ctx->refresh_all_supported = TRUE;
} }
ctx->step++;
setup_sim_hot_swap_step (task); setup_sim_hot_swap_step (task);
} }
@@ -4006,15 +4003,14 @@ uim_check_get_slot_status_ready (QmiClientUim *client,
output = qmi_client_uim_get_slot_status_finish (client, res, &error); output = qmi_client_uim_get_slot_status_finish (client, res, &error);
if (!output || !qmi_message_uim_get_slot_status_output_get_result (output, &error)) { if (!output || !qmi_message_uim_get_slot_status_output_get_result (output, &error)) {
/* Jump to refresh events registration */
mm_obj_dbg (self, "slot status retrieval failed: %s", error->message); mm_obj_dbg (self, "slot status retrieval failed: %s", error->message);
ctx->step = SETUP_SIM_HOT_SWAP_STEP_UIM_REFRESH_REGISTER_ALL;
} else { } else {
/* Go on to next step */ /* Go on to next step */
mm_obj_dbg (self, "slot status retrieval succeeded"); mm_obj_dbg (self, "slot status retrieval succeeded");
ctx->step++; ctx->get_slot_status_supported = TRUE;
} }
ctx->step++;
setup_sim_hot_swap_step (task); setup_sim_hot_swap_step (task);
} }
@@ -4035,15 +4031,14 @@ uim_register_events_ready (QmiClientUim *client,
* we cannot use slot status indications to detect eUICC profile switches. */ * we cannot use slot status indications to detect eUICC profile switches. */
output = qmi_client_uim_register_events_finish (client, res, &error); output = qmi_client_uim_register_events_finish (client, res, &error);
if (!output || !qmi_message_uim_register_events_output_get_result (output, &error)) { if (!output || !qmi_message_uim_register_events_output_get_result (output, &error)) {
/* Jump to refresh events registration */
mm_obj_dbg (self, "not registered for slot status indications: %s", error->message); mm_obj_dbg (self, "not registered for slot status indications: %s", error->message);
ctx->step = SETUP_SIM_HOT_SWAP_STEP_UIM_REFRESH_REGISTER_ALL;
} else { } else {
/* Go on to next step */
mm_obj_dbg (self, "registered for slot status indications"); mm_obj_dbg (self, "registered for slot status indications");
ctx->step++; ctx->register_slot_status_supported = TRUE;
} }
/* Go on to next step */
ctx->step++;
setup_sim_hot_swap_step (task); setup_sim_hot_swap_step (task);
} }
@@ -4082,6 +4077,7 @@ setup_sim_hot_swap_step (GTask *task)
} }
case SETUP_SIM_HOT_SWAP_STEP_UIM_CHECK_SLOT_STATUS: case SETUP_SIM_HOT_SWAP_STEP_UIM_CHECK_SLOT_STATUS:
if (ctx->register_slot_status_supported) {
/* Successful registration does not mean that the modem actually sends /* Successful registration does not mean that the modem actually sends
* physical slot status indications; invoke Get Slot Status to find out if * physical slot status indications; invoke Get Slot Status to find out if
* the modem really supports slot status. */ * the modem really supports slot status. */
@@ -4092,14 +4088,19 @@ setup_sim_hot_swap_step (GTask *task)
(GAsyncReadyCallback) uim_check_get_slot_status_ready, (GAsyncReadyCallback) uim_check_get_slot_status_ready,
task); task);
return; return;
}
ctx->step++;
/* fall-through */
case SETUP_SIM_HOT_SWAP_STEP_UIM_SLOT_STATUS_INDICATION: case SETUP_SIM_HOT_SWAP_STEP_UIM_SLOT_STATUS_INDICATION:
if (ctx->register_slot_status_supported && ctx->get_slot_status_supported) {
mm_obj_dbg (self, "monitoring slot status indications"); mm_obj_dbg (self, "monitoring slot status indications");
g_assert (!priv->uim_slot_status_indication_id); g_assert (!priv->uim_slot_status_indication_id);
priv->uim_slot_status_indication_id = g_signal_connect (priv->uim_client, priv->uim_slot_status_indication_id = g_signal_connect (priv->uim_client,
"slot-status", "slot-status",
G_CALLBACK (uim_slot_status_indication_cb), G_CALLBACK (uim_slot_status_indication_cb),
self); self);
}
ctx->step++; ctx->step++;
/* fall-through */ /* fall-through */
@@ -4127,29 +4128,39 @@ setup_sim_hot_swap_step (GTask *task)
return; return;
} }
case SETUP_SIM_HOT_SWAP_STEP_UIM_REFRESH_REGISTER_ICCID: { case SETUP_SIM_HOT_SWAP_STEP_UIM_REFRESH_REGISTER_ICCID:
/* If refresh all not supported, register for a single file refresh notification */
if (!ctx->refresh_all_supported) {
const guint16 file_path[] = { 0x3F00 }; const guint16 file_path[] = { 0x3F00 };
mm_obj_dbg (self, "register for change in sim iccid"); mm_obj_dbg (self, "register for change in sim iccid");
uim_refresh_register_file (task, 0x2FE2, file_path, G_N_ELEMENTS (file_path)); uim_refresh_register_file (task, 0x2FE2, file_path, G_N_ELEMENTS (file_path));
return; return;
} }
ctx->step++;
/* fall-through */
case SETUP_SIM_HOT_SWAP_STEP_UIM_REFRESH_REGISTER_IMSI: { case SETUP_SIM_HOT_SWAP_STEP_UIM_REFRESH_REGISTER_IMSI:
/* If refresh all not supported, register for a single file refresh notification */
if (!ctx->refresh_all_supported) {
const guint16 file_path[] = { 0x3F00, 0x7FFF }; const guint16 file_path[] = { 0x3F00, 0x7FFF };
mm_obj_dbg (self, "register for change in sim imsi"); mm_obj_dbg (self, "register for change in sim imsi");
uim_refresh_register_file (task, 0x6F07, file_path, G_N_ELEMENTS (file_path)); uim_refresh_register_file (task, 0x6F07, file_path, G_N_ELEMENTS (file_path));
return; return;
} }
ctx->step++;
/* fall-through */
case SETUP_SIM_HOT_SWAP_STEP_UIM_REFRESH_INDICATION: case SETUP_SIM_HOT_SWAP_STEP_UIM_REFRESH_INDICATION:
if (ctx->refresh_all_supported || ctx->refresh_file_supported) {
g_assert (!priv->uim_refresh_indication_id); g_assert (!priv->uim_refresh_indication_id);
priv->uim_refresh_indication_id = priv->uim_refresh_indication_id =
g_signal_connect (priv->uim_client, g_signal_connect (priv->uim_client,
"refresh", "refresh",
G_CALLBACK (uim_refresh_indication_cb), G_CALLBACK (uim_refresh_indication_cb),
self); self);
}
ctx->step++; ctx->step++;
/* fall-through */ /* fall-through */