iface-modem: new logic to detect SIM swap with explicit IMSI/ICCID query
This improves SIM hot swap check process, and it can help avoid unnecessary modem reprobe during suspend-resume without SIM inserted. The changes in this CL implemented the new logic ONLY for MBIM, and the new logic has not been implemented for QMI and AT yet. Thus, we keep the legacy `mm_iface_modem_check_for_sim_swap()' till the new logic for QMI and AT has been implemented.
This commit is contained in:
committed by
Aleksander Morgado
parent
4fdda13c4e
commit
b7433b4c14
@@ -6360,6 +6360,137 @@ modem_setup_sim_hot_swap (MMIfaceModem *_self,
|
||||
task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Check basic SIM details */
|
||||
|
||||
typedef struct {
|
||||
gboolean sim_inserted;
|
||||
gchar *iccid;
|
||||
gchar *imsi;
|
||||
} SimDetails;
|
||||
|
||||
static void sim_details_free (SimDetails *sim_info) {
|
||||
g_free (sim_info->iccid);
|
||||
g_free (sim_info->imsi);
|
||||
g_slice_free (SimDetails, sim_info);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
modem_check_basic_sim_details_finish (MMIfaceModem *self,
|
||||
GAsyncResult *res,
|
||||
gboolean *sim_inserted,
|
||||
gchar **iccid,
|
||||
gchar **imsi,
|
||||
GError **error)
|
||||
{
|
||||
SimDetails *sim_info;
|
||||
|
||||
sim_info = g_task_propagate_pointer (G_TASK (res), error);
|
||||
if (!sim_info)
|
||||
return FALSE;
|
||||
|
||||
*sim_inserted = sim_info->sim_inserted;
|
||||
if (iccid)
|
||||
*iccid = g_steal_pointer (&sim_info->iccid);
|
||||
if (imsi)
|
||||
*imsi = g_steal_pointer (&sim_info->imsi);
|
||||
sim_details_free (sim_info);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
basic_sim_details_subscriber_ready_state_ready (MbimDevice *device,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
MMBroadbandModemMbim *self;
|
||||
g_autoptr(MbimMessage) response = NULL;
|
||||
GError *error = NULL;
|
||||
gchar *imsi = NULL;
|
||||
g_autofree gchar *raw_iccid = NULL;
|
||||
MbimSubscriberReadyState ready_state = MBIM_SUBSCRIBER_READY_STATE_NOT_INITIALIZED;
|
||||
|
||||
self = g_task_get_source_object (task);
|
||||
|
||||
response = mbim_device_command_finish (device, res, &error);
|
||||
if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
|
||||
g_task_return_error (task, error);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mbim_device_check_ms_mbimex_version (device, 3, 0)) {
|
||||
if (!mbim_message_ms_basic_connect_v3_subscriber_ready_status_response_parse (
|
||||
response,
|
||||
&ready_state, /* ready_state */
|
||||
NULL, /* flags */
|
||||
&imsi, /* subscriber id */
|
||||
&raw_iccid, /* sim_iccid */
|
||||
NULL, /* ready_info */
|
||||
NULL, /* telephone_numbers_count */
|
||||
NULL,
|
||||
&error))
|
||||
g_prefix_error (&error, "Failed processing MBIMEx v3.0 subscriber ready status response: ");
|
||||
else
|
||||
mm_obj_dbg (self, "processed MBIMEx v3.0 subscriber ready status response");
|
||||
} else {
|
||||
if (!mbim_message_subscriber_ready_status_response_parse (
|
||||
response,
|
||||
&ready_state, /* ready_state */
|
||||
&imsi, /* subscriber id */
|
||||
&raw_iccid, /* sim_iccid */
|
||||
NULL, /* ready_info */
|
||||
NULL, /* telephone_numbers_count */
|
||||
NULL,
|
||||
&error))
|
||||
g_prefix_error (&error, "Failed processing subscriber ready status response: ");
|
||||
else
|
||||
mm_obj_dbg (self, "processed subscriber ready status response");
|
||||
}
|
||||
|
||||
if (error)
|
||||
g_task_return_error (task, error);
|
||||
else {
|
||||
SimDetails *sim_details;
|
||||
g_autoptr(GError) inner_error = NULL;
|
||||
|
||||
sim_details = g_slice_new0 (SimDetails);
|
||||
if (ready_state != MBIM_SUBSCRIBER_READY_STATE_SIM_NOT_INSERTED) {
|
||||
sim_details->sim_inserted = TRUE;
|
||||
sim_details->iccid = mm_3gpp_parse_iccid (raw_iccid, &inner_error);
|
||||
if (!sim_details->iccid) {
|
||||
mm_obj_warn (self, "can not get ICCID info: couldn't parse SIM ICCID: %s", inner_error->message);
|
||||
}
|
||||
sim_details->imsi = imsi;
|
||||
}
|
||||
g_task_return_pointer (task, sim_details, (GDestroyNotify)sim_details_free);
|
||||
}
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
modem_check_basic_sim_details (MMIfaceModem *self,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MbimDevice *device;
|
||||
GTask *task;
|
||||
g_autoptr(MbimMessage) message = NULL;
|
||||
|
||||
if (!peek_device (self, &device, callback, user_data))
|
||||
return;
|
||||
|
||||
task = g_task_new (self, NULL, callback, user_data);
|
||||
|
||||
message = mbim_message_subscriber_ready_status_query_new (NULL);
|
||||
mbim_device_command (device,
|
||||
message,
|
||||
10,
|
||||
NULL,
|
||||
(GAsyncReadyCallback)basic_sim_details_subscriber_ready_state_ready,
|
||||
task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Enable/Disable unsolicited events (3GPP interface) */
|
||||
|
||||
@@ -9911,6 +10042,8 @@ iface_modem_init (MMIfaceModem *iface)
|
||||
/* SIM hot swapping */
|
||||
iface->setup_sim_hot_swap = modem_setup_sim_hot_swap;
|
||||
iface->setup_sim_hot_swap_finish = modem_setup_sim_hot_swap_finish;
|
||||
iface->check_basic_sim_details = modem_check_basic_sim_details;
|
||||
iface->check_basic_sim_details_finish = modem_check_basic_sim_details_finish;
|
||||
|
||||
/* Other actions */
|
||||
#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED
|
||||
|
||||
@@ -4315,20 +4315,12 @@ sim_swap_check_step (GTask *task)
|
||||
|
||||
case SIM_SWAP_CHECK_STEP_ICCID_CHANGED:
|
||||
ctx->retries = SIM_SWAP_CHECK_LOAD_RETRIES_MAX;
|
||||
/* We may or may not get the new SIM identifier (iccid). In case
|
||||
* we've got it, the load_sim_identifier phase can be skipped. */
|
||||
if (ctx->iccid)
|
||||
complete_sim_swap_check (task, ctx->iccid);
|
||||
else
|
||||
load_sim_identifier (task);
|
||||
load_sim_identifier (task);
|
||||
return;
|
||||
|
||||
case SIM_SWAP_CHECK_STEP_IMSI_CHANGED:
|
||||
ctx->retries = SIM_SWAP_CHECK_LOAD_RETRIES_MAX;
|
||||
if (ctx->imsi)
|
||||
complete_sim_swap_check (task, ctx->imsi);
|
||||
else
|
||||
load_sim_imsi (task);
|
||||
load_sim_imsi (task);
|
||||
return;
|
||||
|
||||
case SIM_SWAP_CHECK_STEP_LAST:
|
||||
@@ -4347,8 +4339,6 @@ sim_swap_check_step (GTask *task)
|
||||
|
||||
static void
|
||||
modem_check_for_sim_swap (MMIfaceModem *self,
|
||||
const gchar *iccid,
|
||||
const gchar *imsi,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
@@ -4360,8 +4350,6 @@ modem_check_for_sim_swap (MMIfaceModem *self,
|
||||
task = g_task_new (self, NULL, callback, user_data);
|
||||
ctx = g_slice_new0 (SimSwapContext);
|
||||
ctx->step = SIM_SWAP_CHECK_STEP_FIRST;
|
||||
ctx->iccid = g_strdup (iccid);
|
||||
ctx->imsi = g_strdup (imsi);
|
||||
g_task_set_task_data (task, ctx, (GDestroyNotify)sim_swap_context_free);
|
||||
|
||||
g_object_get (self,
|
||||
|
||||
+74
-18
@@ -140,6 +140,60 @@ mm_iface_modem_check_for_sim_swap_finish (MMIfaceModem *self,
|
||||
return g_task_propagate_boolean (G_TASK (res), error);
|
||||
}
|
||||
|
||||
static void
|
||||
check_basic_sim_details_ready (MMIfaceModem *self,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
g_autoptr(MMBaseSim) sim = NULL;
|
||||
GError *error = NULL;
|
||||
const gchar *old_iccid = NULL;
|
||||
const gchar *old_imsi = NULL;
|
||||
g_autofree gchar *current_iccid = NULL;
|
||||
g_autofree gchar *current_imsi = NULL;
|
||||
gboolean sim_inserted;
|
||||
|
||||
if (!MM_IFACE_MODEM_GET_INTERFACE (self)->check_basic_sim_details_finish (
|
||||
self, res, &sim_inserted, ¤t_iccid, ¤t_imsi, &error)) {
|
||||
mm_obj_warn (self, "SIM details check failed: %s", error->message);
|
||||
g_task_return_error (task, error);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_get (self, MM_IFACE_MODEM_SIM, &sim, NULL);
|
||||
if (sim) {
|
||||
old_iccid = mm_gdbus_sim_get_sim_identifier (MM_GDBUS_SIM (sim));
|
||||
old_imsi = mm_gdbus_sim_get_imsi (MM_GDBUS_SIM (sim));
|
||||
}
|
||||
|
||||
if (!sim && !sim_inserted) {
|
||||
mm_obj_info (self, "No SIM inserted before and after");
|
||||
} else if (sim && !sim_inserted) {
|
||||
mm_obj_info (self, "SIM removed");
|
||||
mm_iface_modem_process_sim_event (self);
|
||||
} else if (!sim && sim_inserted) {
|
||||
mm_obj_info (self, "SIM inserted");
|
||||
mm_iface_modem_process_sim_event (self);
|
||||
} else if ((g_strcmp0 (current_iccid, old_iccid) != 0) ||
|
||||
(g_strcmp0 (current_imsi, old_imsi) != 0)) {
|
||||
mm_obj_info (self, "new SIM detected");
|
||||
mm_obj_info (self, "ICCID: %s -> %s",
|
||||
mm_log_str_personal_info (old_iccid),
|
||||
mm_log_str_personal_info (current_iccid));
|
||||
mm_obj_info (self, "IMSI: %s -> %s",
|
||||
mm_log_str_personal_info (old_imsi),
|
||||
mm_log_str_personal_info (current_imsi));
|
||||
mm_iface_modem_process_sim_event (self);
|
||||
} else {
|
||||
mm_obj_info (self, "SIM not changed. ICCID: %s, IMSI: %s",
|
||||
mm_log_str_personal_info (current_iccid),
|
||||
mm_log_str_personal_info (current_imsi));
|
||||
}
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
explicit_check_for_sim_swap_ready (MMIfaceModem *self,
|
||||
GAsyncResult *res,
|
||||
@@ -159,8 +213,6 @@ explicit_check_for_sim_swap_ready (MMIfaceModem *self,
|
||||
|
||||
void
|
||||
mm_iface_modem_check_for_sim_swap (MMIfaceModem *self,
|
||||
const gchar *iccid,
|
||||
const gchar *imsi,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
@@ -168,21 +220,29 @@ mm_iface_modem_check_for_sim_swap (MMIfaceModem *self,
|
||||
|
||||
task = g_task_new (self, NULL, callback, user_data);
|
||||
|
||||
if (!MM_IFACE_MODEM_GET_INTERFACE (self)->check_for_sim_swap ||
|
||||
!MM_IFACE_MODEM_GET_INTERFACE (self)->check_for_sim_swap_finish) {
|
||||
mm_obj_info (self, "checking for SIM swap ignored: not implemented");
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
if (MM_IFACE_MODEM_GET_INTERFACE (self)->check_basic_sim_details &&
|
||||
MM_IFACE_MODEM_GET_INTERFACE (self)->check_basic_sim_details_finish) {
|
||||
mm_obj_info (self, "started checking for basic SIM details...");
|
||||
MM_IFACE_MODEM_GET_INTERFACE (self)->check_basic_sim_details (
|
||||
self,
|
||||
(GAsyncReadyCallback)check_basic_sim_details_ready,
|
||||
task);
|
||||
return;
|
||||
}
|
||||
|
||||
mm_obj_info (self, "started checking for SIM swap...");
|
||||
MM_IFACE_MODEM_GET_INTERFACE (self)->check_for_sim_swap (
|
||||
self,
|
||||
iccid,
|
||||
imsi,
|
||||
(GAsyncReadyCallback)explicit_check_for_sim_swap_ready,
|
||||
task);
|
||||
if (MM_IFACE_MODEM_GET_INTERFACE (self)->check_for_sim_swap &&
|
||||
MM_IFACE_MODEM_GET_INTERFACE (self)->check_for_sim_swap_finish) {
|
||||
mm_obj_info (self, "started checking for SIM swap...");
|
||||
MM_IFACE_MODEM_GET_INTERFACE (self)->check_for_sim_swap (
|
||||
self,
|
||||
(GAsyncReadyCallback)explicit_check_for_sim_swap_ready,
|
||||
task);
|
||||
return;
|
||||
}
|
||||
|
||||
mm_obj_info (self, "checking for SIM swap ignored: not implemented");
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -4421,8 +4481,6 @@ interface_enabling_step (GTask *task)
|
||||
MM_IFACE_MODEM_GET_INTERFACE (self)->check_for_sim_swap_finish) {
|
||||
MM_IFACE_MODEM_GET_INTERFACE (self)->check_for_sim_swap (
|
||||
self,
|
||||
NULL,
|
||||
NULL,
|
||||
(GAsyncReadyCallback)check_for_sim_swap_ready,
|
||||
task);
|
||||
return;
|
||||
@@ -4618,8 +4676,6 @@ interface_syncing_step (GTask *task)
|
||||
*/
|
||||
mm_iface_modem_check_for_sim_swap (
|
||||
self,
|
||||
NULL,
|
||||
NULL,
|
||||
(GAsyncReadyCallback)sync_detect_sim_swap_ready,
|
||||
task);
|
||||
return;
|
||||
|
||||
+10
-5
@@ -291,14 +291,22 @@ struct _MMIfaceModem {
|
||||
* Useful for when the modem changes power states since we might
|
||||
* not get the relevant notifications from the modem. */
|
||||
void (*check_for_sim_swap) (MMIfaceModem *self,
|
||||
const gchar *iccid,
|
||||
const gchar *imsi,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean (*check_for_sim_swap_finish) (MMIfaceModem *self,
|
||||
GAsyncResult *res,
|
||||
GError **error);
|
||||
|
||||
void (*check_basic_sim_details) (MMIfaceModem *self,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean (*check_basic_sim_details_finish) (MMIfaceModem *self,
|
||||
GAsyncResult *res,
|
||||
gboolean *sim_inserted,
|
||||
gchar **iccid,
|
||||
gchar **imsi,
|
||||
GError **error);
|
||||
|
||||
/* Asynchronous flow control setup */
|
||||
void (*setup_flow_control) (MMIfaceModem *self,
|
||||
GAsyncReadyCallback callback,
|
||||
@@ -599,8 +607,6 @@ void mm_iface_modem_bind_simple_status (MMIfaceModem *self,
|
||||
|
||||
/* Check if the SIM or eSIM profile has changed */
|
||||
void mm_iface_modem_check_for_sim_swap (MMIfaceModem *self,
|
||||
const gchar *iccid,
|
||||
const gchar *imsi,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean mm_iface_modem_check_for_sim_swap_finish (MMIfaceModem *self,
|
||||
@@ -613,5 +619,4 @@ void mm_iface_modem_modify_sim (MMIfaceModem *self,
|
||||
|
||||
void mm_iface_modem_process_sim_event (MMIfaceModem *self);
|
||||
|
||||
|
||||
#endif /* MM_IFACE_MODEM_H */
|
||||
|
||||
+2
-2
@@ -3649,7 +3649,7 @@ uim_start_refresh_timeout (MMSharedQmi *self)
|
||||
|
||||
mm_obj_dbg (self, "refresh start timed out; trigger SIM change check");
|
||||
|
||||
mm_iface_modem_check_for_sim_swap (MM_IFACE_MODEM (self), NULL, NULL, NULL, NULL);
|
||||
mm_iface_modem_check_for_sim_swap (MM_IFACE_MODEM (self), NULL, NULL);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
@@ -3715,7 +3715,7 @@ uim_refresh_indication_cb (QmiClientUim *client,
|
||||
g_source_remove (priv->uim_refresh_start_timeout_id);
|
||||
priv->uim_refresh_start_timeout_id = 0;
|
||||
}
|
||||
mm_iface_modem_check_for_sim_swap (MM_IFACE_MODEM (self), NULL, NULL, NULL, NULL);
|
||||
mm_iface_modem_check_for_sim_swap (MM_IFACE_MODEM (self), NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,8 +432,6 @@ quectel_qusim_unsolicited_handler (MMPortSerialAt *port,
|
||||
mm_obj_dbg (self, "checking SIM swap");
|
||||
MM_IFACE_MODEM_GET_INTERFACE (self)->check_for_sim_swap (
|
||||
self,
|
||||
NULL,
|
||||
NULL,
|
||||
(GAsyncReadyCallback)quectel_qusim_check_for_sim_swap_ready,
|
||||
NULL);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user