[PATCH v3] mm-iface-modem: add check_for_sim_swap method and enable steps
Aleksander Morgado
aleksander at aleksander.es
Mon Dec 18 09:19:26 UTC 2017
On 13/12/17 19:17, Eric Caruso wrote:
> When in low-power mode, some modems will not dispatch unsolicited
> notifications, such as for SIM hot swapping. There is code in
> MMBroadbandModemTelit to handle this by checking the SIM identifier
> during modem power up against the identifier cached in the SIM
> D-Bus object. If they're different, the SIM has likely been
> swapped while we were powered down.
>
> We can move this code out to MMBroadbandModem because it doesn't
> actually rely on any Telit-specific details, and invoke it from
> MMIfaceModem via a new method.
> ---
Pushed to git master, thanks!
> plugins/telit/mm-broadband-modem-telit.c | 128 ++-----------------------------
> src/mm-broadband-modem.c | 128 +++++++++++++++++++++++++++++++
> src/mm-iface-modem.c | 32 ++++++++
> src/mm-iface-modem.h | 10 +++
> 4 files changed, 176 insertions(+), 122 deletions(-)
>
> diff --git a/plugins/telit/mm-broadband-modem-telit.c b/plugins/telit/mm-broadband-modem-telit.c
> index 995ae6a9..08917ca4 100644
> --- a/plugins/telit/mm-broadband-modem-telit.c
> +++ b/plugins/telit/mm-broadband-modem-telit.c
> @@ -911,20 +911,6 @@ modem_load_unlock_retries (MMIfaceModem *self,
>
> /*****************************************************************************/
> /* Modem after power up (Modem interface) */
> -typedef enum {
> - AFTER_POWER_UP_STEP_FIRST,
> - AFTER_POWER_UP_STEP_GET_SIM_IDENTIFIER,
> - AFTER_POWER_UP_STEP_ENABLE_QSS_PARSING,
> - AFTER_POWER_UP_STEP_LAST
> -} ModemAfterPowerUpStep;
> -
> -typedef struct {
> - gboolean has_sim_changed;
> - guint retries;
> - ModemAfterPowerUpStep step;
> -} AfterPowerUpContext;
> -
> -static void after_power_up_step (GTask *task);
>
> static gboolean
> modem_after_power_up_finish (MMIfaceModem *self,
> @@ -934,123 +920,21 @@ modem_after_power_up_finish (MMIfaceModem *self,
> return g_task_propagate_boolean (G_TASK (res), error);
> }
>
> -static void
> -load_sim_identifier_ready (MMBaseSim *sim,
> - GAsyncResult *res,
> - GTask *task)
> -{
> - AfterPowerUpContext *ctx;
> - GError *error = NULL;
> - gchar *current_simid;
> - const gchar *cached_simid;
> -
> - ctx = g_task_get_task_data (task);
> -
> - cached_simid = (gchar *)mm_gdbus_sim_get_sim_identifier (MM_GDBUS_SIM (sim));
> - current_simid = mm_base_sim_load_sim_identifier_finish (sim, res, &error);
> -
> - if (error) {
> - if (g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED)) {
> - mm_warn ("could not load SIM identifier: %s", error->message);
> - g_clear_error (&error);
> - goto out;
> - }
> -
> - if (ctx->retries-- > 0) {
> - mm_warn ("could not load SIM identifier: %s (%d retries left)",
> - error->message, ctx->retries);
> - g_clear_error (&error);
> - g_timeout_add_seconds (1, (GSourceFunc) after_power_up_step, task);
> - return;
> - }
> -
> - mm_warn ("could not load SIM identifier: %s", error->message);
> - g_clear_error (&error);
> - goto out;
> - }
> -
> - if (g_strcmp0 (current_simid, cached_simid) != 0) {
> - mm_warn ("sim identifier has changed: possible SIM swap during power down/low");
> - ctx->has_sim_changed = TRUE;
> - }
> -
> -out:
> - g_free (current_simid);
> - ctx->step++;
> - after_power_up_step (task);
> -}
> -
> -static void
> -after_power_up_step (GTask *task)
> -{
> - AfterPowerUpContext *ctx;
> - MMBroadbandModemTelit *self;
> -
> - ctx = g_task_get_task_data (task);
> - self = g_task_get_source_object (task);
> -
> - switch (ctx->step) {
> - case AFTER_POWER_UP_STEP_FIRST:
> - /* Fall back on next step */
> - ctx->step++;
> -
> - case AFTER_POWER_UP_STEP_GET_SIM_IDENTIFIER: {
> - MMBaseSim *sim = NULL;
> -
> - g_object_get (MM_BROADBAND_MODEM_TELIT (self),
> - MM_IFACE_MODEM_SIM, &sim,
> - NULL);
> - if (!sim) {
> - g_task_return_new_error (task,
> - MM_CORE_ERROR,
> - MM_CORE_ERROR_FAILED,
> - "could not acquire sim object");
> - g_object_unref (task);
> - return;
> - }
> -
> - mm_base_sim_load_sim_identifier (sim,
> - (GAsyncReadyCallback)load_sim_identifier_ready,
> - task);
> - g_object_unref (sim);
> - return;
> - }
> -
> - case AFTER_POWER_UP_STEP_ENABLE_QSS_PARSING:
> - mm_dbg ("Stop ignoring #QSS");
> - self->priv->parse_qss = TRUE;
> -
> - /* Fall back on next step */
> - ctx->step++;
> - case AFTER_POWER_UP_STEP_LAST:
> - if (ctx->has_sim_changed)
> - mm_broadband_modem_update_sim_hot_swap_detected (MM_BROADBAND_MODEM (self));
> -
> - g_task_return_boolean (task, TRUE);
> - g_object_unref (task);
> - break;
> - default:
> - g_assert_not_reached ();
> - }
> -}
> -
> static void
> modem_after_power_up (MMIfaceModem *self,
> GAsyncReadyCallback callback,
> gpointer user_data)
> {
> GTask *task;
> - AfterPowerUpContext *ctx;
> -
> - ctx = g_new0 (AfterPowerUpContext, 1);
> - ctx->step = AFTER_POWER_UP_STEP_FIRST;
> - ctx->has_sim_changed = FALSE;
> - ctx->retries = 3;
> + MMBroadbandModemTelit *modem = MM_BROADBAND_MODEM_TELIT (self);
>
> task = g_task_new (self, NULL, callback, user_data);
> - g_task_set_task_data (task, ctx, (GDestroyNotify) g_free);
>
> - after_power_up_step (task);
> + mm_dbg ("Stop ignoring #QSS");
> + modem->priv->parse_qss = TRUE;
> +
> + g_task_return_boolean (task, TRUE);
> + g_object_unref (task);
> }
>
> /*****************************************************************************/
> diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
> index c97afc13..f82122b1 100644
> --- a/src/mm-broadband-modem.c
> +++ b/src/mm-broadband-modem.c
> @@ -3356,6 +3356,132 @@ modem_power_up (MMIfaceModem *self,
> g_object_unref (task);
> }
>
> +/*****************************************************************************/
> +/* Reprobing the modem if the SIM changed across a power-off or power-down */
> +
> +typedef struct {
> + MMBaseSim *sim;
> + guint retries;
> +} SimSwapContext;
> +
> +static gboolean load_sim_identifier (GTask *task);
> +
> +static void
> +sim_swap_context_free (SimSwapContext *ctx)
> +{
> + g_clear_object (&ctx->sim);
> + g_slice_free (SimSwapContext, ctx);
> +}
> +
> +static gboolean
> +modem_check_for_sim_swap_finish (MMIfaceModem *self,
> + GAsyncResult *res,
> + GError **error)
> +{
> + return g_task_propagate_boolean (G_TASK (res), error);
> +}
> +
> +static void
> +load_sim_identifier_ready (MMBaseSim *sim,
> + GAsyncResult *res,
> + GTask *task)
> +{
> + MMBroadbandModem *self;
> + SimSwapContext *ctx;
> + const gchar *cached_simid;
> + gchar *current_simid;
> + GError *error = NULL;
> +
> + self = MM_BROADBAND_MODEM (g_task_get_source_object (task));
> + ctx = g_task_get_task_data (task);
> + cached_simid = mm_gdbus_sim_get_sim_identifier (MM_GDBUS_SIM (sim));
> + current_simid = MM_BASE_SIM_GET_CLASS (sim)->load_sim_identifier_finish (sim, res, &error);
> +
> + if (error) {
> + if (g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED)) {
> + g_task_return_error (task, error);
> + goto out;
> + }
> +
> + if (ctx->retries > 0) {
> + mm_warn ("could not load SIM identifier: %s (%d retries left)",
> + error->message, ctx->retries);
> + --ctx->retries;
> + g_clear_error (&error);
> + g_timeout_add_seconds (1, (GSourceFunc) load_sim_identifier, task);
> + return;
> + }
> +
> + mm_warn ("could not load SIM identifier: %s", error->message);
> + g_task_return_error (task, error);
> + goto out;
> + }
> +
> + if (g_strcmp0 (current_simid, cached_simid) != 0) {
> + mm_info ("sim identifier has changed: possible SIM swap during power down/low");
> + mm_broadband_modem_update_sim_hot_swap_detected (self);
> + }
> +
> + g_task_return_boolean (task, TRUE);
> +
> +out:
> + g_free (current_simid);
> + g_object_unref (task);
> +}
> +
> +static gboolean
> +load_sim_identifier (GTask *task)
> +{
> + SimSwapContext *ctx = g_task_get_task_data (task);
> +
> + MM_BASE_SIM_GET_CLASS (ctx->sim)->load_sim_identifier (
> + ctx->sim,
> + (GAsyncReadyCallback)load_sim_identifier_ready,
> + task);
> +
> + return G_SOURCE_REMOVE;
> +}
> +
> +static void
> +modem_check_for_sim_swap (MMIfaceModem *self,
> + GAsyncReadyCallback callback,
> + gpointer user_data)
> +{
> + GTask *task;
> + SimSwapContext *ctx;
> +
> + mm_dbg ("Checking if SIM was swapped...");
> +
> + task = g_task_new (self, NULL, callback, user_data);
> + ctx = g_slice_new0 (SimSwapContext);
> + ctx->retries = 3;
> + g_task_set_task_data (task, ctx, (GDestroyNotify)sim_swap_context_free);
> +
> + g_object_get (self,
> + MM_IFACE_MODEM_SIM, &ctx->sim,
> + NULL);
> + if (!ctx->sim) {
> + g_task_return_new_error (task,
> + MM_CORE_ERROR,
> + MM_CORE_ERROR_FAILED,
> + "could not acquire sim object");
> + g_object_unref (task);
> + return;
> + }
> +
> + if (!MM_BASE_SIM_GET_CLASS (ctx->sim)->load_sim_identifier ||
> + !MM_BASE_SIM_GET_CLASS (ctx->sim)->load_sim_identifier_finish) {
> + g_task_return_new_error (task,
> + MM_CORE_ERROR,
> + MM_CORE_ERROR_FAILED,
> + "sim identifier could not be loaded");
> + g_object_unref (task);
> + return;
> + }
> +
> + load_sim_identifier (task);
> +}
> +
> /*****************************************************************************/
> /* Sending a command to the modem (Modem interface) */
>
> @@ -10767,6 +10893,8 @@ iface_modem_init (MMIfaceModem *iface)
> /* Enabling steps */
> iface->modem_power_up = modem_power_up;
> iface->modem_power_up_finish = modem_power_up_finish;
> + iface->check_for_sim_swap = modem_check_for_sim_swap;
> + iface->check_for_sim_swap_finish = modem_check_for_sim_swap_finish;
> iface->setup_flow_control = modem_setup_flow_control;
> iface->setup_flow_control_finish = modem_setup_flow_control_finish;
> iface->load_supported_charsets = modem_load_supported_charsets;
> diff --git a/src/mm-iface-modem.c b/src/mm-iface-modem.c
> index afb3be32..7236e30b 100644
> --- a/src/mm-iface-modem.c
> +++ b/src/mm-iface-modem.c
> @@ -3557,6 +3557,7 @@ static void interface_enabling_step (GTask *task);
> typedef enum {
> ENABLING_STEP_FIRST,
> ENABLING_STEP_SET_POWER_STATE,
> + ENABLING_STEP_CHECK_FOR_SIM_SWAP,
> ENABLING_STEP_FLOW_CONTROL,
> ENABLING_STEP_SUPPORTED_CHARSETS,
> ENABLING_STEP_CHARSET,
> @@ -3606,6 +3607,25 @@ enabling_set_power_state_ready (MMIfaceModem *self,
> interface_enabling_step (task);
> }
>
> +static void
> +check_for_sim_swap_ready (MMIfaceModem *self,
> + GAsyncResult *res,
> + GTask *task)
> +{
> + EnablingContext *ctx;
> + GError *error = NULL;
> +
> + if (!MM_IFACE_MODEM_GET_INTERFACE (self)->check_for_sim_swap_finish (self, res, &error)) {
> + mm_warn ("Error checking if SIM was swapped: '%s'", error->message);
> + g_error_free (error);
> + }
> +
> + /* Go on to next step */
> + ctx = g_task_get_task_data (task);
> + ctx->step++;
> + interface_enabling_step (task);
> +}
> +
> static void
> setup_flow_control_ready (MMIfaceModem *self,
> GAsyncResult *res,
> @@ -3709,6 +3729,18 @@ interface_enabling_step (GTask *task)
> task);
> return;
>
> + case ENABLING_STEP_CHECK_FOR_SIM_SWAP:
> + if (MM_IFACE_MODEM_GET_INTERFACE (self)->check_for_sim_swap &&
> + MM_IFACE_MODEM_GET_INTERFACE (self)->check_for_sim_swap_finish) {
> + MM_IFACE_MODEM_GET_INTERFACE (self)->check_for_sim_swap (
> + self,
> + (GAsyncReadyCallback)check_for_sim_swap_ready,
> + task);
> + return;
> + }
> + /* Fall down to next step */
> + ctx->step++;
> +
> case ENABLING_STEP_FLOW_CONTROL:
> if (MM_IFACE_MODEM_GET_INTERFACE (self)->setup_flow_control &&
> MM_IFACE_MODEM_GET_INTERFACE (self)->setup_flow_control_finish) {
> diff --git a/src/mm-iface-modem.h b/src/mm-iface-modem.h
> index d25fbd49..177bf910 100644
> --- a/src/mm-iface-modem.h
> +++ b/src/mm-iface-modem.h
> @@ -281,6 +281,16 @@ struct _MMIfaceModem {
> GAsyncResult *res,
> GError **error);
>
> + /* Asynchronous check to see if the SIM was swapped.
> + * 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,
> + GAsyncReadyCallback callback,
> + gpointer user_data);
> + gboolean (*check_for_sim_swap_finish) (MMIfaceModem *self,
> + GAsyncResult *res,
> + GError **error);
> +
> /* Asynchronous flow control setup */
> void (*setup_flow_control) (MMIfaceModem *self,
> GAsyncReadyCallback callback,
>
--
Aleksander
https://aleksander.es
More information about the ModemManager-devel
mailing list